UI測試
本文翻譯自Chris Grant的《iOS9 Day-by-Day :: Day 2 :: UI Testing》(https://www.shinobicontrols.com/blog/ios9-day-by-day-day2-ui-testing)。感謝Chris Grant的辛苦工作!
自動化用戶界面測試在開發應用程序的時候非常有用。它可以快速檢測程序中的問題。iOS系統使用JavaScript編寫的UIAutomation樣例進行測試。整個過程涉及啟動程序、Instruments以及創建和運行腳本。這個工作流程需要花一點時間才能適應。
UI測試
在Xcode 7中,蘋果引入了一種新的方法來管理應用程序的UI測試。它允許我們查找和操作UI元素,并且檢查它們的屬性和狀態。UI測試已經被完全整合到Xcode 7的測試報告中,并且與單元測試一起運行。Xcode 5整合的XCTest框架,在Xcode 7的時候被更新成支持UI測試。它支持在檢查某個UI狀態后執行斷言。
輔助功能
為了進行UI測試,這個框架必須能夠訪問應用程序UI中的各個元素。這樣它才能操作這些控件。我們可以定義手指頭點擊、滑動的位置。但這在不同尺寸的設備上沒法正常工作。
這時輔助功能(無障礙環境)就有用了。輔助功能是蘋果專門為殘疾人與應用進行交互而維護的一個框架。它給UI界面提供了豐富的語義數據,以便殘疾人通過這些輔助功能操作應用程序。iOS提供了越來越多的這種功能。雖然它們可能只能在某個應用里使用,但我們還是應該去改進這些API所使用的數據。在很多場景下這都是必要的,比如自定義控件的輔助功能沒有自動識別出API的功能。
UI測試有能力通過輔助功能操作我們的應用,并且能夠自動適應不同設備尺寸。當我們對界面進行重新布局時,不需要重寫測試樣例。輔助功能還能讓殘疾人更方便的使用我們的程序。
UI錄制
一旦設置好可以訪問的UI后,我們就可創建測試樣例了。如果界面比較復雜的話,編寫UI測試樣例是一個費事、無聊的事情。不過在Xcode 7里,蘋果引入了UI錄制,它允許我們創建新測試、擴展已有測試。啟動UI錄制后,只要在設備或模擬器里與程序進行交互,就會自動生成測試代碼。總體了解了UI測試后,下面實際動手試試。
創建UI測試樣例
下面的例子里,我們使用最新的測試工具來創建測試樣例。最終的示例代碼可以在Github上找到。
設置
在Xcode 7中創建項目時,我們可以選擇包含UI測試(include UI Tests)。它會自動幫我們創建一個UI測試目標,并設置好所有需要的內容。

這個示例非常簡單,但包含了演示Xcode 7的UI測試功能所需要的內容。
這是一個菜單頁面,它包含一個開關和按鈕,其中按鈕鏈接到詳情頁面。當開關處于關閉狀態時,按鈕被禁用。詳情頁面包含一個簡單的按鈕,點擊后增加標簽上顯示的值。
使用UI錄制
一旦設置好UI以及對應的功能。我們就可以開始編寫UI測試樣例來確保界面上的任何修改都不會影響程序的功能。
XCTest UI測試接口
在開始錄制動作之前,需要確定判斷條件。XCTest框架判斷UI上元素的功能被分為下面三組API:
-
XCUIApplication
:所測試應用的代理,允許啟動應用程序作為測試目標。它總是啟動一個新進程。這樣做消耗的時間稍微多一點,但是能夠保證測試環境不被干擾,處理的變量更少。 -
XCUIElement
:程序中UI控件的代理。所有元素都擁有自己的類型和標識,用來查找程序中的任何一個元素。程序中的所有元素都被嵌套成一個樹形結構。 -
XCUIElementQuery
:用于查詢元素。每個XCUIElement
都有一個查詢支撐。這類查詢會遍歷整個元素樹,然后精確的匹配一個元素。如果沒有匹配上,則測試失敗。當我們檢查一個元素是否在這棵樹上時,有一個例外就是exists
屬性。這個屬性用作判斷的時候非常有用。我們可以使用更加通用的XCUIElementQuery
進行查詢。它會返回一個結果集。
了解了API后就可以開始寫測試樣例了。
測試1-確保開關關閉時不會發生導航
首先我們訂一個一個函數用來包含測試代碼。
func testTapViewDetailWhenSwitchIsOffDoesNothing() {
}
然后將光標移動到花括號中間,并且點擊錄制Xcode下方的按鈕。

應用程序開始啟動,點擊開關將它關閉,然后點擊“View Detail”按鈕。在剛才的testTapViewDtailWhenSwitchIsOffDoesNothing
會出現一下代碼:
let app = XCUIApplication()
app.switches["View Detail Enabled Switch"].tap()
app.buttons["View Detail".tap()
再次點擊錄制按鈕,停止錄制。我們可以看到,應用程序并沒有顯示詳情頁面,但是測試樣例并不知道這件事。我們必須加入判斷語句,是否有內容發生改變。這可以通過檢測導航條上的標題做到。這樣做雖然不能滿足所有條件,但都與目前的情況來說已經足夠了。
XCTAssertEqual(app.navigationBars.element.identifier, "Menu")
重新運行測試,它還是會通過。我們將“Menu”字符串改為“Detail”,這時測試就會失敗了。給測試樣例添加一些注釋:
func testTapViewDetailWhenSwitchIsOffDoesNothing() {
let app = XCUIApplication()
//關閉開關
app.switches["View Detail Enabled Switch"].tap()
//點擊查看詳情按鈕
app.buttons["View Detail"].tap()
//驗證是否還停留在菜單頁
XCTAssertEqual(app.navigaionBars.element.identifier, "Menu")
}
測試2-確保開關打開時導航條發生改變
第二個測試與第一個非常類似,因此我們不再詳細介紹。唯一不同的地方是,這里的開關是打開的,因此應用程序應該會加載詳情頁面,并且XCTAssertEqual
會確認這一點。
func testTapViewDetailWhenSwitchIsOnNavigatesToDetailViewController() {
let app = XCUIApplication()
//點擊詳情按鈕
app.buttons["View Detail"].tap()
//驗證導航條標識
XCTAssertEqual(app.navigationBars.element.identifier, "Detail")
}
測試3-確保遞增按鈕正常工作
在這個測試中,我們確保用戶點擊遞增按鈕后,標簽上的值會加1。測試代碼的前兩行非常類似,因此直接將它從上面復制下來就可以了。
let app = XCUIApplication()
//點擊詳情按鈕,打開頁面
app.buttons["View Detail"].tap()
下一步,獲取按鈕。需要點擊這個按鈕多次,因此先將它存儲在一個變量中。我們還是可以進行錄制。代碼如下:
app.buttons["Increment Value"].tap()
停止錄制,并且將代碼改為:
let incrementButton = app.buttons["Increment Value"]
這樣我們就不再需要手動寫代碼查找按鈕。下面是查找標簽的代碼:
let valueLabel = app.staticTexts["Number Value Label"]
到目前為止,我們已經獲取了所有感興趣的控件。在這個測試里,我們將驗證10次點擊后,標簽上的值是否正確。還是可以使用錄制功能,點擊十次按鈕。不過之前已經將元素全部保存,因此只需要簡單的輸入一個循環就可以。
for index in 0...10 {
//點擊按鈕
incrementButton.tap()
//確保每次增1
XCTAssertEqual(valueLabel.value as! String, "\(index+1)")
}
這是整個測試包里的三個而已,但是給我們提供了非常好的切入點,并且很容易在這個上面進行擴充。為什么不嘗試自己增加一些測試樣例來驗證當開關打開時按鈕可以點擊,關閉時不能點擊?
錄制出錯
錄制的時候,可能會發現當我們點擊按鈕后,并沒有產生代碼。這是因為交互的元素并不支持輔助功能。我們需要使用Xcode的“Accessibility Inspector”進行檢查。
一旦輔助功能檢查器被打開,按“Command+F7”,然后用鼠標覆蓋一個元素。這時我們會看到光標下元素的詳細信息。這會提示我們輔助功能到底能否找到該元素。
測試失敗
如果測試失敗,并且我們不知道為什么。這里有一些方法可以幫助我們。首先,訪問Xcode的測試報告。
當我們打開這個視圖,并且鼠標懸停在某個步驟時就會看到測試動作的右邊有一個小眼睛一樣的圖標。如果點擊這個眼睛,就可以看到該測試的詳情信息。這樣就可以可視化的檢查UI狀態,并且找出具體是哪里有問題。
與單元測試類似,我們可以給UI測試設置斷點。這樣就可以對行為進行調試,并且找出問題。當測試失敗時,可以查看視圖結構以及檢查輔助功能的屬性。
為什么需要UI測試
自動化UI測試能夠極大的保障程序質量。在Xcode中進行測試非常簡單,并且給程序增加輔助功能不只是幫助我們進行測試,還能提高對殘疾人的友好度。
Xcode中的UI測試能夠直接在持續集成服務器上運行。當測試失敗時,我們可以通過Xcode機器人或者命令行方式立即獲取信息。
擴展閱讀
關于Xcode UI測試的更多信息,建議觀看WWDC session 406:“UI Testing in Xcode”。或者查看文檔:“Testing in Xcode Document”和“Accessibility for Developers Documentation”。
戴維營教育
戴維營教育(Dive In Education),潛心做IT職業教育!緊跟時代潮流,不弄虛作假!不忘初心!