天天看點

swift單元測試(五)三方UI測試架構KIF的使用

1、KIF介紹

         KIF的全稱是Keep it functional。它是一個建立在XCTest的UI測試架構,通過accessibility來定位具體的控件,再利用私有的API來操作UI。由于是建立在XCTest上的,是以你可以完美的借助XCode的測試相關工具(包括指令行腳本

         使用KIF架構強制要求你的代碼支援accessibility。如果你之前沒接觸過,可以看看Apple的文檔Accessibility Programming Guide for iOS。

         簡單來說,accessibility能夠讓視覺障礙人士使用你的App。每一個控件都有一個描述AccessibilityLabel。在開啟VoiceOver的時候,點選控件就可以選中并且聽到對應的描述。通常UIKit的控件是支援accessibility的,自定定義控件可以通過代碼或者Storyboard上設定。

2、KIF使用

1)cocopod導入KIF架構

pod 'KIF', '~> 3.0'           

2)在建立的UI測試檔案中導入,測試類繼承類改成 KIFTestCase

import KIF           

3)在項目中進行配置

(1)“Build Phases”:

設定 Target Dependencies , UI 自動化測試固然要依賴應用程式的 App 産物,是以需保證應用程式 Target 被添加在 Test Target 的 Target Dependencies 中。

(2)“Build Settings”:     

設定 “Bundle loader” 為:$(BUILT_PRODUCTS_DIR)/MyApp.app/MyApp;     

設定 “Test Host” 為:$(BUILT_PRODUCTS_DIR);     設定 “Wrapper Extensions” 為:xctest。           

4)配置控件的AccessibilityLabel屬性

有3種配置方式

(1)通過Runtime Attributes設定(KVC)

swift單元測試(五)三方UI測試架構KIF的使用

(2)通過GUI來設定,選中控件,找到下圖所示的位置,填寫AccessibilityLabel屬性

swift單元測試(五)三方UI測試架構KIF的使用

(3)通過代碼來設定

kifBtn.accessibilityLabel = "KIF"           

5)具體使用

(1)KIF時OC寫的,Swift無法直接使用其關鍵方法tester、system(通過宏定義),參照GitHub README,通過extension實作

在UI測試檔案中書寫

extension XCTestCase {
    func tester(file : String = #file,_ line : Int = #line)->KIFUITestActor{
        return KIFUITestActor(inFile: file, atLine: line, delegate: self)
    }
    func system(file : String = #file,_ line : Int = #line)->KIFSystemTestActor{
        return KIFSystemTestActor(inFile: file, atLine: line, delegate: self)
    }
}           

(2)KIF的使用

操作步驟:

點選button按鈕-->跳轉至登入界面-->輸入使用者名、密碼,點選login-->跳轉至tab導航界面,切換不同tab的操作流程

class LoginTestCase: KIFTestCase {
    /// 所有測試進行前調用,可以做一些必要或者共有的初始化操作
    override func beforeAll() {

    }

    /// 測試點選登陸後進入其他View
    func test00Login() {
        tester().tapView(withAccessibilityLabel: "button")
        tester().waitForView(withAccessibilityLabel: "login")
        
        let nameTextField = tester().waitForView(withAccessibilityLabel: "UserName") as! UITextField
        let pwdTextField = tester().waitForView(withAccessibilityLabel: "Password") as! UITextField
        tester().enterText("User", intoViewWithAccessibilityLabel: "UserName")
        tester().enterText("123456", intoViewWithAccessibilityLabel: "Password")
        // 點選
        tester().tapView(withAccessibilityLabel: "login")
        XCTAssertTrue(!nameTextField.text!.isEmpty, "User name can't be nil")
        XCTAssertTrue(!pwdTextField.text!.isEmpty, "Password can't be nil")

        // 等待某個View出現,也可以通過該函數得到該View的執行個體
        tester().waitForView(withAccessibilityLabel: "Scene1")
    }

    /// 測試切換不同的View
    func test01TabButtons() {
        tester().tapView(withAccessibilityLabel: "Tab2")
        tester().waitForView(withAccessibilityLabel: "Scene2")

        tester().tapView(withAccessibilityLabel: "Tab3")
        tester().waitForView(withAccessibilityLabel: "Scene3")
    }

    /// 測試輸入
    func test02Input() {
        tester().tapView(withAccessibilityLabel: "Tab1")
        tester().waitForView(withAccessibilityLabel: "InputTextField")
        // 輸入文字
        tester().enterText("Hello KIF", intoViewWithAccessibilityLabel: "InputTextField")

        // TODO: 如何确定鍵盤彈出的done按鈕的accessibilityLabel?
        tester().tapView(withAccessibilityLabel: "Scene1View")

        // 得到View執行個體
        let textfield = tester().waitForView(withAccessibilityLabel: "InputTextField") as! UITextField
        // 判斷是否相等
        XCTAssertEqual(textfield.text, "Hello KIF")

        // 清除目前文字重新輸入新的
        tester().clearText(fromAndThenEnterText: "Test Geometry", intoViewWithAccessibilityLabel: "InputTextField")
        tester().tapView(withAccessibilityLabel: "Scene1View")
    }

    /// 有的時候無法确定accessibilityLabel或者是自定義的空間沒有accessibilityLabel,可以使用Geometry計算位置進行
    func test03Geometry() {
        tester().wait(forTimeInterval: 2)

        let stepper = tester().waitForView(withAccessibilityLabel: "stepper") as! UIStepper
        let stepCenter = stepper.window?.convert(stepper.center, from: stepper.superview)
        // 算出-和+的位置
        var minusButton = stepCenter
        minusButton?.x -= stepper.frame.width / 4
        var plusButton = stepCenter
        plusButton?.x += stepper.frame.width / 4

        for _ in 0 ..< 10 {
            tester().wait(forTimeInterval: 1)
            tester().tapScreen(at: minusButton!)
        }

        // 延時1秒
        tester().wait(forTimeInterval: 1)
        tester().tapScreen(at: plusButton!)
        tester().wait(forTimeInterval: 1)
        tester().tapScreen(at: plusButton!)
        tester().wait(forTimeInterval: 1)

        // 設定逾時時間(預設為10秒)
        KIFUITestActor.setDefaultTimeout(60)

        tester().tapView(withAccessibilityLabel: "Tab2")

        KIFUITestActor.setDefaultTimeout(10)
    }

}           

KIF API中文翻譯(一)

基于 KIF 的 iOS UI 自動化測試和持續內建

iOS自動化測試的那些幹貨