一、兩種技術(shù)的比較
XCode的自動化測試包括:UnitTests與UITests,即:單元測試與界面測試。EarlGrey是Google在UnitTests的基礎(chǔ)上開發(fā)的界面測試庫,與UITests相似,同時具有一定的優(yōu)勢。具體如下:
二、UITests使用教程
Quick Start
1、新建項目,在以下界面勾選Unit Tests與UI Tests。

2、如果是老項目:點擊菜單-Editor-Add Target,并在以下界面選擇iOS UI Testing Bundle

3、給新的Target起名

4、在項目可以看到新添加的Target與對應(yīng)的文件夾

5、查看自動生成的UITests代碼,本例為UITestsSample.swift。默認(rèn)生成testExample測試方法。注:所有待測試的方法均以test開頭

6、編寫測試代碼,詳見下方說明
7、點擊Test Navigator,這里將所有Target、其下測試類、以及測試方法列了出來,是按字母排序的。點擊右側(cè)的三角形按鈕即開始測試,可對指定方法、指定類、指定Target進(jìn)行測試。按Command+U則依次測試所有Target

8、測試完成后,在以下界面會顯示測試結(jié)果,綠勾表示成功或紅叉表示失敗

9、下圖為報告,左側(cè)列出了所有測試報告列表(也包括每次的編譯報告),右側(cè)為某次測試報告詳情。具體每一個測試步驟的情況(時間、截圖等)均會顯示。

UITests核心類介紹
1、XCUIApplication:對應(yīng)UIApplication,對App進(jìn)行操作。主要方法有:
init() / init(bundleID):得到當(dāng)前App實例,也可通過bundleID得到其他App實例,如:模擬打開微信時需要用到。
launch():啟動App
activate():激活A(yù)pp
terminate():中止App
state: runningForeground/runningBackground/notRunning:得到App狀態(tài)
wait(for state: XCUIApplication.State,? timeout: TimeInterval) -> Bool:等待App狀態(tài)變?yōu)槟持禃r,并設(shè)置了超時時間
2、XCUIElement:對應(yīng)界面上的元素。主要方法有:
exists:判斷元素是否存在
waitForExistence(timeout:) -> Bool:等待元素出現(xiàn)
children(matching: ElementType) -> XCUIElementQuery:獲取一級子元素
descendants(matching: XCUIElement.ElementType) -> XCUIElementQuery:獲取所有子元素
typeText(String):模擬鍵盤輸入,并填入文本框中
tap() / doubleTap() / press(forDuration:) / press(forDuration: thenDragTo:) / twoFingerTap() / swipeLeft/Right/Up/Down() / pinch() / rotate():各類操作
3、XCUIElementQuery:查找元素的規(guī)則。主要方法有:
allElementsBoundByIndex: [XCUIElement]:返回該規(guī)劃對應(yīng)的所有元素集合
count: Int:返回該規(guī)劃對應(yīng)的所有元素數(shù)量
element: XCUIElement:返回該規(guī)劃對應(yīng)的單個元素
element(boundBy: Int) -> XCUIElement:按下標(biāo)返回該規(guī)劃對應(yīng)的元素。boundBy貌似是根據(jù)各元素的x、y坐標(biāo)排序的。(類似先上后下、先左后右,具體排序規(guī)則未知)
element(matching: XCUIElement.ElementType, identifier: String?) -> XCUIElement:按元素類型、id返回
children(matching: ElementType) -> XCUIElementQuery:返回指定類型的子元素查詢規(guī)則
descendants(matching: XCUIElement.ElementType) -> XCUIElementQuery:返回指定類型的后代元素查詢規(guī)則
4、其他重要類
XCUIScreen:對屏幕的操作,如截屏等
XCTAttachment:附件類,如需要將截屏包裝成Attachment才能添加到測試報告中
XCTActivity:上下文,如添加Attachment的方法就在其中
Asynchronous:對異步操作的捕獲
????????XCTKVOExpectation:對KVO值changed的捕獲
????????XCTNSNotificationExpectation:對通知的捕獲
Assert functions:各種斷言方法,如下:

UITests代碼實例說明
```
importXCTest
classUITestsSample:XCTestCase{
? ? //自動生成的代碼,所有testXXX執(zhí)行前均會執(zhí)行它
? ? overridefuncsetUp() {
? ? ? ? //出錯后是否繼續(xù)
? ? ? ? continueAfterFailure = false
? ? ? ? XCUIApplication().launch()
? ? }
? ? //自動生成的代碼,所有testXXX執(zhí)行后均會執(zhí)行它
? ? overridefunctearDown() {
? ? }
? ? //測試打開微信
? ? functestWeixin() {
? ? ? ? letapp =XCUIApplication(bundleIdentifier:"com.tencent.xin")
? ? ? ? app.activate()
? ? ? ? //模擬點擊“我”tab
? ? ? ? app.tabBars.buttons["我"].tap()
? ? ? ? //模擬點擊“支付”菜單
? ? ? ? app.tables.staticTexts["支付"].tap()
? ? }
? ? functestLoginPerformance() {
? ? ? ? //對sampleFun方法進(jìn)行性能測試,系統(tǒng)會嘗試多次(約10次),并生成性能報告。測試完后,self.measure代碼左側(cè)會出現(xiàn)一個灰色按鈕,點擊查看報告
? ? ? ? self.measure{
? ? ? ? ? ? sampleFun()
? ? ? ? }
? ? }
? ? functestAddReminder() {
? ? ? ? sampleFun()
? ? }
? ? funcsampleFun() {
? ? ? ? letapp =XCUIApplication()
? ? ? ? //查找accessibilityIdentifier=login的按鈕,并點擊它。注:accessibilityIdentifier需要在App主代碼中設(shè)置
? ? ? ? app.buttons["login"].tap()
? ? ? ? //查找日期按鈕并點擊
? ? ? ? app.datePickers["date"].tap()
? ? ? ? //按靜態(tài)文本查找
? ? ? ? app.staticTexts["登錄"].tap()
? ? ? ? //查找第1個UITableView
? ? ? ? app.tables.element(boundBy:0)
? ? ? ? //是否存在靜態(tài)文本為“注冊”的視圖
? ? ? ? ifapp.staticTexts["注冊"].exists{
? ? ? ? }
? ? ? ? //等待“注冊”出現(xiàn),最多等10秒,如果出現(xiàn)了就返回true
? ? ? ? ifapp.staticTexts["注冊"].waitForExistence(timeout:10) {
? ? ? ? }
? ? ? ? //層層查找。注:這種方法不可靠,主App代碼變動會導(dǎo)致視圖結(jié)構(gòu)變動
? ? ? ? app.children(matching: .table).children(matching: .button)
? ? ? ? //判斷“注冊“是否存在,不存在則認(rèn)為異常,拋出異常信息
? ? ? ? XCTAssertTrue(app.staticTexts["注冊"].exists,"注冊按鈕不存在")
? ? }
}
```