iOS開發:UI Tests探索筆記

來源:互聯網
上載者:User

   UI Tests是什麼?

  UI Tests是一個自動化的測試UI與互動的Testing組件

  UI Tests有什麼用?

  它可以通過編寫代碼、或者是記錄開發人員的操作過程並代碼化,來實現自動點擊某個按鈕、視圖,或者自動輸入文字等功能。

  UI Tests的重要性

  在實際的開發過程中,隨著項目越做越大,功能越來越多,僅僅靠人工操作的方式來覆蓋所有測試案例是非常困難的,尤其是加入新功能以後,舊的功能也要重新測試一遍,這導致了測試需要花非常多的時間來進行迴歸測試,這裡產生了大量重複的工作,而這些重複的工作有些是可以自動完成的,這時候UI Tests就可以協助解決這個問題了。

  使用方法

  第一步:添加UI Tests

  如果是新項目,則建立工程的時候可以直接勾選選項,如下圖

  如果是已有的項目,可以通過添加target的方式添加一個UI Tests,點擊xcode的菜單,找到target欄

  在Test選項中選擇Cocoa Touch UI Testing Bundle

  這時候test組件添加成功,它在項目中的位置如下圖所示

  第二步:建立測試代碼

  手動建立測試代碼

  開啟測試檔案,在testExample()方法中添加測試代碼

  如果不知道如何寫測試代碼,則可以參考自動產生的程式碼樣式

  自動產生測試步驟

  選擇測試檔案後,點擊錄製按鈕

  這時候開始進行操作,它會記錄你的操作步驟,並產生測試代碼

  下圖就是在一些操作後自動產生的測試代碼

  這時候可以分析測試代碼的文法,以便你自己手動修改或者手寫測試代碼

  開始測試

  點擊testExample方法旁邊的播放按鈕,它就開始進行自動化的測試了,這時候你會看到app在自動操作

  下面介紹一下測試元素的文法

  XCUIApplication:

  繼承XCUIElement,這個類掌管應用程式的生命週期,裡麵包含兩個主要方法

  launch():

  啟動程式

  terminate():

  終止程式

  XCUIElement:

  繼承NSObject,實現協議XCUIElementAttributes, XCUIElementTypeQueryProvider

  可以表示系統的各種UI元素

  exist:

  可以讓你判斷當前的UI元素是否存在,如果對一個不存在的元素進行操作,會導致測試組件拋出異常並中斷測試

  descendantsMatchingType(type:XCUIElementType)->XCUIElementQuery:

  取某種類型的元素以及它的子類集合

  childrenMatchingType(type:XCUIElementType)->XCUIElementQuery:

  取某種類型的元素集合,不包含它的子類

  這兩個方法的區別在於,你僅使用系統的UIButton時,用childrenMatchingType就可以了,如果你還希望查詢自己定義的子Button,就要用descendantsMatchingType

  另外UI元素還有一些互動方法

  tap(): 點擊

  doubleTap(): 雙擊

  pressForDuration(duration: NSTimeInterval): 長按一段時間,在你需要進行延時操作時,這個就派上用場了

  swipeUp(): 這個響應不了pan手勢,暫時沒發現能用在什麼地方,也可能是beta版的bug,先不解釋

  typeText(text: String): 用於textField和textView輸入文本時使用,使用前要確保文字框獲得輸入焦點,可以使用tap()函數使其獲得焦點

  XCUIElementAttributes協議

  裡麵包含了UIAccessibility中的部分屬性

  如下圖

  可以方便你查看當前元素的特徵,其中identifier屬性可用於直接讀取元素,不過該屬性在UITextField中有bug,暫時不清楚原因

  XCUIElementTypeQueryProvider協議

  裡麵包含了系統中大部分UI控制項的類型,可通過讀屬性的方式取得某種類型的UI集合

  部分屬性截圖如下

  建立Demo

  首先建立一個登入頁面

  點擊login按鈕進行登入驗證,點擊clear按鈕會清除文本

  登入成功後可以去到個人資訊頁面

  個人資訊頁面如下

  點擊modify按鈕可以修改個人資訊,點擊Message按鈕可以查看個人訊息

  最後是訊息介面

  登入頁面的測試

  輸入一個錯誤的帳號

  驗證結果

  關閉警告窗

  清除輸入記錄

  輸入一個正確的帳號

  驗證結果

  進入個人資訊頁面

  測試代碼如下:

  func testLoginView() {

  let app = XCUIApplication()

  // 由於UITextField的id有問題,所以只能通過label的方式遍曆元素來讀取

  let nameField = self.getFieldWithLbl("nameField")

  if self.canOperateElement(nameField) {

  nameField!.tap()

  nameField!.typeText("xiaoming")

  }

  let psdField = self.getFieldWithLbl("psdField")

  if self.canOperateElement(psdField) {

  psdField!.tap()

  psdField!.typeText("1234321")

  }

  // 通過UIButton的預設id來讀取對應的按鈕

  let loginBtn = app.buttons["Login"]

  if self.canOperateElement(loginBtn) {

  loginBtn.tap()

  }

  // 開始一段延時,由於真實的登入是連網請求,所以不能直接獲得結果,demo通過延時的方式來類比連網請求

  let window = app.windows.elementAtIndex(0)

  if self.canOperateElement(window) {

  // 延時3秒, 3秒後如果登入成功,則自動進入資訊頁面,如果登入失敗,則彈出警告窗

  window.pressForDuration(3)

  }

  // alert的id和labe都用不了,估計還是bug,所以只能通過數量判斷

  if app.alerts.count > 0 {

  // 登入失敗

  app.alerts.collectionViews.buttons["確定"].tap()

  let clear = app.buttons["Clear"]

  if self.canOperateElement(clear) {

  clear.tap()

  if self.canOperateElement(nameField) {

  nameField!.tap()

  nameField!.typeText("sun")

  }

  if self.canOperateElement(psdField) {

  psdField!.tap()

  psdField!.typeText("111111")

  }

  if self.canOperateElement(loginBtn) {

  loginBtn.tap()

  }

  if self.canOperateElement(window) {

  // 延時3秒, 3秒後如果登入成功,則自動進入資訊頁面,如果登入失敗,則彈出警告窗

  window.pressForDuration(3)

  }

  self.loginSuccess()

  }

  } else {

  // 登入成功

  self.loginSuccess()

  }

  }

  這裡有幾個需要特別注意的點:

  1. 當你的元素不存在時,它仍然可能返回一個元素對象,但這時候不能對其進行操作

  2. 當你要點擊的元素被鍵盤或者UIAlertView遮擋時,執行tap方法會拋異常

  詳細實現可參照demo: https://github.com/sunGd/demo/tree/master/iOS9/UITestDemo

  個人資訊頁測試

  修改性別

  修改年齡

  修改心情

  儲存修改

  測試代碼如下:

  func testInfo() {

  let app = XCUIApplication()

  let window = app.windows.elementAtIndex(0)

  if self.canOperateElement(window) {

  // 延時2秒, 載入資料需要時間

  window.pressForDuration(2)

  }

  let modifyBtn = app.buttons["modify"];

  modifyBtn.tap()

  let sexSwitch = app.switches["sex"]

  sexSwitch.tap()

  let incrementButton = app.buttons["Increment"]

  incrementButton.tap()

  incrementButton.tap()

  incrementButton.tap()

  app.buttons["Decrement"].tap()

  let textView = app.textViews["feeling"]

  textView.tap()

  app.keys["Delete"].tap()

  app.keys["Delete"].tap()

  textView.typeText(" abc ")

  // 點擊空白地區

  let clearBtn = app.buttons["clearBtn"]

  clearBtn.tap()

  // 儲存資料

  modifyBtn.tap()

  window.pressForDuration(2)

  let messageBtn = app.buttons["message"]

  messageBtn.tap();

  // 延時1秒, push view需要時間

  window.pressForDuration(1)

  self.testMessage()

  }

  這裡需要特別注意以下兩點:

  1. textview擷取焦點時無法選擇焦點的位置

  2. tap事件的觸發位置是view的中心,所以當view的中心被遮擋時,要考慮使用其他view來代替

  個人訊息介面測試

  儲存格的點擊

  測試代碼如下:

  func testMessage() {

  let app = XCUIApplication()

  let window = app.windows.elementAtIndex(0)

  if self.canOperateElement(window) {

  // 延時2秒, 載入資料需要時間

  window.pressForDuration(2)

  }

  let table = app.tables

  table.childrenMatchingType(.Cell).elementAtIndex(8).tap()

  table.childrenMatchingType(.Cell).elementAtIndex(1).tap()

  }

  這裡需要注意一點:

  1. 暫時無法擷取到tableView的元素指標

  總結

  總的來說,UI Tests只能用於一些基礎功能的測試,驗證app的功能是否可以正常使用,是否存在崩潰問題。但它也有很多不足之處,編寫測試案例的過程非常繁瑣,自動產生的程式碼幾乎無法運行,功能單一,很多用例無法覆蓋,而且bug很多,大大地限制了UI Tests在實際開發中的應用。希望正式版出來的時候能夠修複這些問題,並開放更多的功能。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.