解放程式猿(媛)的雙手—iOS UI自動化測試
轉載地址:http://tmq.qq.com/2016/06/uitestingiosautomation/?utm_source=tuicool&utm_medium=referral
隨著移動網際網路時代的蓬勃發展,移動終端的自動化測試也在業界日益活躍,總體來看在Android平臺上的自動化工具和實踐比較多,但是說到iOS平臺無論從自動化工具的數量還是質量上就陡降了。究其原因,無外乎是iOS系統的封閉性,加上相對Android使用者的數量少,導致對這個平臺系統的自動化進展緩慢,據筆者瞭解到的情況,很多iOS平臺的測試人員還處於純手工測試模式,自動化程度和Android平臺無法相論,更別提和PC端相比了。
然而越是困難的事,越是研究的少,就越發有挑戰性。有挑戰性的事大多又會帶來不菲的收益,如果能在iOS上做出大規模可持續執行的自動化測試,那麼對iOS的測試演進無疑是一次大的推動。
手機QQ瀏覽器(iPhone)測試小組的同學在比對和實踐了業界已有的iOS自動化工具,總結提煉了對比,如下表所示。
表中沒有列的內容是穩定性,實踐中看來上述除UITesting之外的工具穩定性都相對一般,會出現自身框架導致的各種閃退,以及效能越來越差的問題。
因此iOS平臺上除了Monkey測試採用了自動化方式,以及部分效能測試輕度使用了一些自動化工具,大部分功能測試還是依賴於人的操作。移動APP更多的場景是面向使用者,面向介面操作,UI測試就非常直觀和重要,因此我們致力於尋找一種穩定性高,且易於掌握的自動化測試工具。
蘋果公司在2015年推出的Xcode7中引入了UI Testing工具,該工具配置相對簡單,還支援錄製回放功能,執行速度很快,測試程式碼也可以除錯,使用OC作為指令碼測試語言相容性較好,支援UIWebView,支援截圖功能,最重要的是穩定性高。
其實選用一個工具,最看重的就是穩定性和可除錯。可除錯性不必多說,就是剛需。而很多工具沒有被很好的應用就是因為穩定性較差,UI Testing是蘋果開發的,和被測程式的相容性好,實踐證明,確實能夠徹夜穩定執行指令碼,未見因工具自身原因導致的閃退。效能方面也影響較小,後期發現一些截圖操作會有一點點影響速度,但是整體執行還算良好,沒有明顯變差。
在大量工具都無法在iOS上施展拳腳時,UI testing姍姍而來,帶給我們驚喜和希望。
工具是好工具,但是如果想在專案中實際應用起來,還是會遇到許多問題和困難,這裡給大家分享下我們的磨合期。
要使用這個工具,撲面而來的問題就是怎樣快速上手,也即學習成本和投入產出比的問題。地球人都知道OC語言並不是一種容易快速上手學習的語言,加上底層是XCTest介面,錄製後能看到的實現就是下圖這樣的,看著很凌亂有沒有?
因此我們需要做的就是進行封裝。封裝包含介面封裝和特殊控制元件的封裝兩部分。
介面封裝有兩層,一層主要處理彈窗,異常,超時等待,手勢處理等操作,二層是把控制元件型別和手勢合二為一,提供指令碼使用。實際指令碼編寫者就可以直接呼叫,命名和使用方式都具備高可讀性和可用性,另一方面底層的介面修改,不會影響到上層的函式表現形式,這對自動化用例編者來說也降低了門檻,不必關注底層介面的細節變動。
例如上圖所示,瀏覽器多視窗介面向左滑動就可以刪除頁面,可以選擇刪除第一個頁面。將這個操作封裝起來如下圖所示,後續使用即可直接呼叫該函式,只需傳入對應引數即可。
特殊控制元件的封裝。一般應用於控制元件無法尋找到對應的唯一標識,或者層級比較多的情況下,通過錄制的方式,讀取控制元件屬性,將其打包成一個整體,再後續使用時可以直接呼叫。
例如上圖所示是瀏覽器多視窗的管理介面,右下角有個返回按鈕,通過檢視xml結構無法獲知唯一標識,通過錄制的方式確定控制元件結構。對錄製的內容進行加工處理後,封裝為特殊控制元件,如下圖所示,存放於指定檔案內,方便後續使用。
使用中,可以直接呼叫已經封裝好的介面,每個介面都包含一個或者多個固定引數,和一個可變引數。固定引數按照所給出的型別傳值就可以了,而可變引數,需要我們按照一定的格式進行引數傳遞。舉例可變引數格式:VariableParameter:@” StepName=切換小說書架為宮格模式&LogLevel=WARN”,其中多個引數使用&符號連線,每一個單獨的引數使用KEY=VALUE的形式。
在自動化測試中經常遇到的問題是配置環境和單例執行的問題。
首先環境配置會不會很複雜,很大程度上制約著使用者的使用頻率。相比較APPium的複雜設定,UI testing的配置就簡單明瞭多了。
- 新增服務端配置。需要將UITestServer.xcodeproj新增到目標工程的thridparty資料夾下面。UITestServer.xcodeproj是自研伺服器,主要功能是:嵌入被測試APP中,實現埠監聽,服務開啟,訊息獲取,訊息處理,各種事件功能(截圖,獲取被測試APP日誌資訊,獲取記憶體,cpu,網速,流量等功能),還可以擴充套件。
- 配置被測APP。需要在被測APP的主載入函式中加入監聽服務埠。為了不影響釋出版本的使用,我們採用DEBUG模式。
- 配置QBUITests(名字自定義)元件部分,該部分主要是我們的自動化測試框架部分,包括各種自動化元件,自動化指令碼,配置資訊等。需要將自研資料夾UITestUtils,SystemResources,SpecialElement,ScreenShot,Log,ScriptInterface全部拖動到QBUITests Target下面。
經過上面的配置,框架配置基本完成。
接下來看單例執行問題,如下圖所示是小說模組的自動化指令碼頭部,包含開頭的初始化操作,直接可以執行單例“test311001”,也可以進行正常的除錯,也可以指定執行全部用例或者部分指令碼。
第三個挑戰:結果可查
做UI自動化也好,做監控或者准入測試也罷,最終都要有個輸出結果。一般來說對於自動化測試的結果要具備兩點:截圖和日誌。截圖可以時時截圖,也即可以讓自動化設計者或者測試人員隨時獲取想要的結果圖片,也可以設定發生錯誤時自動截圖。日誌系統就要詳細記錄操作過程,在確認問題是可以一步步通過日誌追溯。
UI Testing除了控制元件識別和簡單操作外,並沒有提供螢幕截圖功能,我們需要自己完成螢幕截圖功能,而且還要能夠在各種封裝好的函式中靈活使用截圖功能。如下圖所示,在自動化用例指令碼中使用函式時,可以隨時在可變引數裡設定LogLevel=WARN,即可在操作執行過程中進行截圖。
當然在程式執行異常或者元素找不到的時候也會自動截圖。這些截圖的操作都預設放在封裝函式裡了,使用者不必單獨設定。
系統日誌的獲取分為兩種,一種是過程中的操作記錄,一種是記憶體之類的效能日誌。日誌的獲取需要用到跨程序通訊,前者主要是記錄自動化用例執行過程中的操作步驟和截圖資訊,後者主要是獲取裝置的系統性能資料,例如記憶體、CPU、網路等。生成的本地log如下圖示。
最終整合到日誌系統(後文講解)下圖。
在初次磨合後,基本上有了本地單機執行自動化的能力,但是要真正對專案有所幫助,就必須有比較好的執行方式和結果展示,因此對這個自動化的研究還需要進一步發展。
1)整體架構
首先要對基於UI Testing的自動化整體架構有個瞭解。如下圖所示,使用系統提供的XCTest介面、訊息處理、驅動模組、系統資源獲取,在中間層進行封裝,包括控制元件呼叫封裝,特殊控制元件封裝,截圖模組,日誌處理模組。這些內容在上文都有講述。
關於整體架構的內容在圖中的最上層。一個是整合在XCODE裡邊的自動化執行框架和指令碼,另一個是分析log日誌的自動化log日誌分析系統。如上圖所示是在基於控制元件呼叫驅動的基礎上,使用自動化指令碼和配置檔案完成自動化測試的工作。然後使用日誌分析系統,包含日誌分析、展示、郵件等,給到專案團隊以完整的視覺化報告。
2)日誌系統
日誌分析系統是使用python開發的系統,所以其是獨立於XCODE框架的,當自動化指令碼執行完成後,需要把log日誌傳到分析系統下,然後使用該系統分析出日誌,方便使用者檢視指令碼錯誤資訊,分析定位問題。
自研的日誌分析系統可以將每次執行的日誌升成html格式,如下圖所示。
詳細指令碼日誌介紹,如下圖所示。
步驟詳細資訊,如下圖所示,一般只需關注紅色錯誤資訊。
通過該日誌系統就可以獲得良好的可視效果,方便問題追蹤和回溯。
3)持續整合
功能的自動化測試,最終的期望還是能夠隨著版本進行持續測試。有些比較好的應用場景:准入測試、開發自測、迴歸測試。不管是哪種應用場景,最佳方式都是將自動化框架合入主線,方便專案組的不同成員隨時在任何開發機上執行。
但是!這裡是iOS平臺,有一種憂傷叫做蘋果稽核不通過,有一種致命拒絕叫做查出私有API。雖然配置簡單,合入主線跟隨程式碼構建看起來不是個難事,但是難就難在需要打包升成版本的時候不能將自研部分的伺服器程式碼編譯進去,這部分會經常含有私有API(一些功能的實現必須要用到私有API)。因此我們採用了動態關聯的方式,在主函式所在的檔案中加入下圖所示內容。既能順利將框架合入開發主線,又可以在編包釋出時不編譯這部分程式碼。
凡事都講究個投入產出比,前期做了大量的預研和實踐工作,那究竟在專案實踐中能發揮怎樣的效果呢?接下來為大家展示一下。
1)部署情況
目前手機QQ瀏覽器(iPhone)專案上,已經採用這種基於UI Testing的自動化測試方法進行BVT建設,每天晚上測試白天提交到主線的最新程式碼,保障主線質量穩定,併為第二天早上的提測包做一個准入測試。
在部署時考慮到版本迭代以及UI變更大的問題,主要是在瀏覽器基礎FT上進行了大量自動化測試部署,還對使用者訪問的TOP頁面進行檢測,如下圖所示。確保合入主線的程式碼不會影響到瀏覽器基礎功能,及時發現問題,避擴音測後再暴露問題,造成時間和資源的浪費。
發現有問題的地方還可以進入詳情檢視,如下圖所示點選測試LOG連結。
另外對一些瀏覽服務SDK也進行了自動化測試監控,如下圖所示。
2)投入產出比
投入產出比的問題,要看兩個方面,好比天平的兩端,一端是投入,一段是產出。得產出重過投入才是一個好專案,值得長期運營。
如上圖所示,我們的投入成本可以分成兩塊,分別是一次性成本和線性成本。
一次性成本:框架研發(1個人2個月)+配置和部署(4人0.5天)+學習成本(3人1天)。這個一次性成本主要消耗在框架的研發上,以及測試人員的初始培訓上,後續只有新加入測試人員才會增加這個成本。事實證明在一次性成本上的投入非常值當,好的框架可以保證提高後期運維階段的穩定性和使用的簡易性。
線性成本:自動化用例編寫(平均14分鐘/條),每日需要維護的成本(8分鐘左右)。線性成本隨著時間的推移可能會產生變化,例如自動化用例隨著測試人員的熟練程度單條用例的編寫時間會減少,每日需要維護的成本隨著用例數的增多和需求變動增多會增高,這些都在預期範圍內。
產出方面,我們的評估分為客觀和主觀兩方面。
客觀:
- 前置bug暴露時間。BVT每日執行,因此總會提前於正式提測前暴露問題。目前是部署在主線上,主線的提測頻率大約40天能提測10次左右,也即平均下來差不多4天才能提測一次,一旦BVT發現問題,平均能前置三天發現。由於數量都是平均來算,因此只能大約估值,例如發現了29次問題,前置時間就是29*3天=87天。
- 減少提測拒絕次數,節省人力時間成本。由於BVT裡的自動化用例全部是基礎核心用例,一旦出現執行問題,就是不符合准入測試標準的。在沒有BVT的時代,提測前都是開發手工自測和測試手工驗證的方式進行,一旦發現不符合測試條件的bug,就會打回,這種情況下就會消耗不少的人力和時間。有了BVT後,這種情況大大減輕,開發可以自己執行自動化指令碼做基礎功能自測,測試每日監控也在執行檢測。 目前手工執行一遍自動化的用例大約需要200分鐘,機器在夜晚用60分鐘就搞定,每個版本的拒測次數大約是2次左右。如果用狂野的演算法應該是節約了200*2=400分鐘,低調點的演算法,應該是“從開始測試到發現導致拒測的bug所用的時間”*拒測次數,但是這個資料暫時來說不可考。
主觀:
為什麼要放上主觀收益呢,因為客觀上節省的時間,在主觀上還要有個內心“更淡定”了的感受。總體來說BVT的部署,大大提高了測試在專案組的影響力,從此iOS上的測試從純手工邁入了新時代,每日版本質量也有了持續穩定的檢驗,全專案組的內心也更加淡定了。
3)運營資料
如下圖所示是每日發現問題的統計,金色的線是確認是bug的數量,藍色的是BVT每日報出來的問題,可以看出兩線基本重合的點比較多,這反映了誤報率相對維持在一個比較低的水平。
發現的問題中主要分為三類,如下圖所示,分別是純誤報(因為指令碼的穩定性導致的)、UI變動(包含被測元素變動、需求變更)和真實bug。如下圖所示是統計的兩個月的資料,可以發現UI變動導致的問題佔總發現問題的比例相對較低。這些資料是在沒有與開發約定程式碼規範的時候,隨著後期的合作,這部分UI變動導致的問題中的元素屬性變動問題將會降低,但是純需求變動的問題還是保持一定的比例。
最後,還是需要和讀者交流下這個自動化方案的問題和未來。
目前已知的問題是基於UI Testing的自動化測試方案需要的硬體要求。聯機操作或者模擬器,得有iMac,作業系統得是OS10.10.5及以上版本,Xcode版本得是7.1及以上,Python版本2.7及以上,記憶體2G及以上為佳。沒有這個配置,恐怕無法良好的執行自動化測試。
還有一個性能問題,已經封裝好的工具指令碼總數理論上控制在1000個以內,可穩定執行10小時以上。在這穩定執行的10小時內,可以滿足我們的自動化需求,但是時間超過幾個小時後,還是會有些許減速,可以通過修改底層訊息傳遞機制,提升傳遞效率,減少截圖執行時間,也是今後自動化測試繼續優化的方向。
未來呢,繼續擴大指令碼覆蓋範圍,對特殊控制元件做封裝,對函式的靈活性做優化,降低自動化測試的准入門檻,提升自動化測試的效率,期待更多同行業的牛人一起探討!