iOS UI Testing 指北
iOS 業界有很多 UI 自動化測試框架,ITest_KIF.html" target="_blank" rel="nofollow,noindex">美團有一篇文章 中對主流框架進行了對比,各大框架實現的思路有兩種:基於蘋果的 UI Testing(UI Automation)或者使用私有 API。這裡只介紹蘋果自家的 UI Testing,它是蘋果自 Xcode 7 引入的 UI 自動化測試框架,有幾個優勢:
- Xcode 自帶,不需要搭建環境
- 支援 OC、Swift,學習成本低
- 支援 WebView 測試
- 穩定性好
利用 UI Testing 可以對 app 的 UI 進行黑盒測試。目前還只能做比較簡單的測試工作,基本原理是利用 iOS 的 Accessibility(原本是為幫助殘障人士提供的框架)來查詢 UI 上的元素並模擬點按、滾動等事件,配合對 UI 元素狀態的校驗來檢查測試結果。
使用方法
要使用 UI Testing,只需要新建一個 UI Testing 的 target,Xcode 已經提供了現成的模板,非常方便。整個過程就三步:利用XCUIApplication
和XCUIElementQuery
查詢元素、用XCUIElement
模擬操作、用斷言檢查結果。
-
XCUIApplication
XCUIApplication
代表整個應用,可以用來啟動、結束程序,或者傳入一些啟動引數,最常用的功能是利用XCUIApplication
例項來查詢 UI 上的元素。
XCUIApplication *app = [[XCUIApplication alloc] init]; [app launch]; [app terminate];
-
XCUIElementQuery
XCUIElementQuery
代表一系列的 UI 元素查詢條件,可以級聯使用。常用的使用方法如下:
// 查詢所有的 collectionView 的 cell, collectionViews 和 cells 是 XCUIElementQuery 提供的方法 XCUIElementQuery *cells = app.collectionViews.cells; // 使用 NSPredicate 為查詢條件增加條件 XCUIElementQuery *cells = [app.collectionViews.cells matchingPredicate:[NSPredicate predicateWithFormat:@"identifier LIKE '?labelPrice?'"]]; // 使用下標來通過 accessibilityIdentifier 查詢元素 XCUIElementQuery *cells = app.collectionViews.cells[@"some_id"];
通常一個頁面中相同種類的 UI 元素很多,就需要使用accessibilityIdentifier
來區分不同的元素。
-
XCUIElement
XCUIElement
代表具體的 UI 元素,比如一個 button 或者 scrollView。從XCUIElementQuery
可以得到XCUIElement
。
// 獲取第一個 button XCUIElement *firstButton = [buttons elementBoundByIndex:0]; // 等待 button 出現 [button waitForExistenceWithTimeout:3]
我們還可以通過XCUIElement
的屬性查詢 UI 元素的狀態,比如是否可點選,是否存在。得到 UI 元素呼叫tap
,swipeUp
等方法就可以模擬操作了,使用起來非常方便。除了向指定元素模擬操作之外,還可以使用XCUICoordinate
模擬基於螢幕座標的事件。
UI Testing 是基於 XCTest 開發的,也就可以用 XCTest 提供的一系列斷言用來檢查結果,如XCTAssert
、XCTAssertTrue
等。
常見問題
accessibilityIdentifier
沒有設定
TBUIAutoTest
是一個自動生成accessibilityIdentifier
的工具,原理
是 hookUIView
的accessibilityIdentifier
和accessibilityLabel
方法,通過執行時獲取成員變數名來作為accessibilityIdentifier
。
如何實現暫停 3 秒鐘
測試程式碼是執行在另外一個程序中的,所以sleep(3)
就好。
iOS 11 上向可見的元素髮送事件報錯,提示元素不可見
現象:執行 tap 操作時報 error: Error -25204 performing AXAction 2003 on element pid: 43616, elementOrHash.elementID: 4882574576.240,cell hittable 返回 NO
原因:isAccessibilityElement 方法預設返回 YES,在 iOS 11 上會出現返回 NO 的情況(同樣程式碼 iOS 12 上正常)
解決:需要顯示將該屬性設定為 YES
DOMException Crash
現象:WebView 載入過程中 crash
原因:WebView 載入過程中查詢 UI 元素會導致 crash
解決:
- 使用 WKWebView
-
在
UIWebViewDelegate
中,webView 載入完成前呼叫[self.view setAccessibilityElementsHidden:YES]
,載入完成後呼叫[self.view setAccessibilityElementsHidden:NO]
- sleep 幾秒等待 webView 載入完成 :]
被測試 app 如何判斷正在進行 UI Test?
在啟動 app 時增加一個啟動引數,在 app 中讀取。
// 測試程式碼 XCUIApplication *app = [[XCUIApplication alloc] init]; app.launchEnvironment = @{@"isUITest" : @YES}; [app launch]; // app 程式碼 + (BOOL)isUITesting { NSDictionary *environment = [[NSProcessInfo processInfo] environment]; return [environment[@"isUITest"] boolValue]; }