UI Tests有什麼用?
它可以通過編寫程式碼、或者是記錄開發者的操作過程並程式碼化,來實現自動點選某個按鈕、檢視,或者自動輸入文字等功能。
1. 新增UI Tests
-
如果是新專案,則建立工程的時候可以直接勾選選項,如下圖

-
如果是已有的專案,可以通過新增target的方式新增一個UI Tests,點選xcode的選單,找到target欄並點選,在Test選項中選擇iOS UI Testing Bundle

新增成功
預設的UITests方法都是以test
開頭的。這裡的testExample
是系統自動生成的方法。

2. 新增測試程式碼
有兩種方式
-
手動新增
新手不推薦自己寫,很麻煩,坑也很多。我也是用的自動新增,然後再自己調整。
-
自動新增

3. 再次執行寫好的Test

自動新增的程式碼,你再次執行這個測試用例的時候,不一定能正常執行,會有一些bug,需要再次調整。
注意事項:
- 如果你下一步需要點選的控制元件被某個檢視擋住了,你需要先隱藏遮蓋檢視,再進行點選,否則會報錯。比如在顯示
Hud
的時候和鍵盤彈出
的時候,收鍵盤需用最直觀的方式,類似點選鍵盤上面的return
、Done
,而不是點選空白區域那種。 textField.typeText("")
方法是直接在當前內容的後面進行新增,這裡我是把清空的按鈕在輸入期間顯示了出來,如果需要完全的更改textField
的text
,就先點選清空按鈕。- 獲取到的控制元件資料,基本都是陣列的形式,然後根據一個值來篩選,自動生成的一般是根據
text
或者title
來篩選,某些介面可能存在兩個按鈕的title
一樣,或者兩個textField
的text
一樣,所以需要通過一個額外的屬性來篩選,也就是accessibilityIdentifier
,這個屬性需要手動設定。至於篩選的方法就是類似app.buttons.element(matching: .button, identifier: T_LoginBtn)
。 - 部分控制元件獲取不到可能是因為
isAccessibilityElement
屬性被設定成了NO
,不過這個屬性的預設值是YES
,我也不太清楚什麼情況下他會變成NO
,下面是Apple的註釋。
Return YES if the receiver should be exposed as an accessibility element.
default == NO
default on UIKit controls == YES
Setting the property to YES will cause the receiver to be visible to assistive applications.
複製程式碼
tableView
中獲取cell
上面的控制元件,系統自動生成的程式碼會獲取cell
的集合,然後根據title
或者text
之類的屬性來篩選類似下面這段程式碼,明顯這不是一個好的方式。這種情況我們可以獲取cell
的集合,然後根據index
來選擇指定的cell
。具體的程式碼可以參考下面購物車的測試程式碼。
tablesQuery.cells.containing(.staticText, identifier:"澳洲直郵Devondale德運奶粉高鈣全脂奶粉成人奶粉1kg ")
複製程式碼
- 當程式碼重複進行多次點選的時候,比如寫個
for
迴圈點選50
次,你並不需要考慮點選太快會不會出現什麼問題,因為每次點選的中間,系統都會有個等待響應的時間,只有當程式空閒的時候,才會進行點選。不過,具體執行方式可能不是我說的這樣,不過確實有個類似的等待時間。上面的這種說法只是我自己的理解。 UITests
可以配合斷言來使用,我個人對斷言用的並不是很好,這兩段Demo
裡面並沒有用到斷言,如果需要請自行新增。類似下面的程式碼,就是判斷textField
是否存在。XCTAssertEqual(textField.exists, true)
4. 下面是兩個我寫好的測試程式碼
1. 登入的模擬測試,這個要複雜一些,涉及了介面跳轉和一些重複點選。
2. 購物車的模擬測試,這個主要是給大家看看tableView這類集合檢視的操作。
這是我專案的tabbar
,兩段測試程式碼最開頭都有app.tabBars.buttons["我的"].tap()
這種程式碼,就是tabbar
的切換。程式碼的前面會附上購物車和登入介面的設計圖。



/**
這裡分三步:
1. 國家地區為中國時,判斷手機號是否正確
2. 國家地區不是中國時,判斷手機號是否正確
3. 正確的賬號密碼,登入功能
*/
func testLogin() {
let app = XCUIApplication()
let window = app.windows.element(boundBy: 0)
app.tabBars.buttons["我的"].tap()
window.press(forDuration: 1)
//---------------------1
//找到手機號的輸入框
let textField = app.textFields["請輸入手機號"]
XCTAssertEqual(textField.exists, true)
//點選
textField.tap()
//修改輸入框的輸入
textField.typeText("187027813111")
//獲取清空手機號的按鈕
let clearTextButton = app.textFields["請輸入手機號"].buttons["Clear text"]
//收鍵盤
app.buttons["確定"].tap()
//找到登入按鈕
let button = app.buttons.element(matching: .button, identifier: T_LoginBtn)
//點選登入
button.tap()
//暫停2秒
window.press(forDuration: 2)
//---------------------2
//跳到選擇國家介面
let selectCountry = app.buttons["login arrow"]
selectCountry.tap()
let tablesQuery = app.tables
//選中一個國家並返回
tablesQuery.staticTexts["愛沙尼亞"].tap()
//點選登入
button.tap()
//暫停2秒
window.press(forDuration: 2)
textField.tap()
//清空賬號資訊
clearTextButton.tap()
textField.typeText("18702781315")
//收鍵盤
app.buttons["確定"].tap()
//再次選中國家
selectCountry.tap()
tablesQuery.staticTexts["中國"].tap()
//點選登入
button.tap()
//暫停2秒
window.press(forDuration: 2)
//---------------------3
let pwdTextField = app.secureTextFields.element(matching: .secureTextField, identifier: T_PWDLoginKey)
pwdTextField.tap()
pwdTextField.typeText("123456")
//輸入完成點選確認按鈕
let doneButton = app.buttons["Done"]
doneButton.tap()
button.tap()
}
複製程式碼

/**
購物車的測試模型
*/
func testShopCart() {
let app = XCUIApplication()
app.tabBars.buttons["tab shopcart"].tap()
//獲取tableView的所有cell
let tablesCells = app.tables.cells
//遍歷cell
(0..<tablesCells.count).forEach { (index) in
let cell = tablesCells.element(boundBy: index)
cell.buttons["shopCart add"].tap()
cell.buttons["shopCart add"].tap()
cell.buttons["shopCart add"].tap()
cell.buttons["shopCart reduce"].tap()
cell.buttons["shopCart reduce"].tap()
cell.buttons["shopcart unselect"].tap()
cell.buttons["shopcart unselect"].tap()
}
}
複製程式碼
參考連結: