本章では、iOSでXCUITestを用いた、UIテストの作成方法について共有します。
XCUITestとは
XCUITestは、XCodeに付属したUI上でテストを実行できるテストフレームワークです。
XCUITestでは、アプリのUI要素に対して、タップ、スワイプ、スクロールといったユーザーの操作を伴った動作確認ができます。
XCUITestにより、UIテストの自動化ができ、特に回帰テスト中に時間を節約できます。
AndroidのEspresso同様、XCode上の操作記録ツールを利用することで、コードの作成なくテストケースの作成もできます。
XCUITestによるUIテストの作成
事前準備
まずは、テスト開始前に常に初期設定となるよう、アプリを削除する処理を準備しておきます。用意の仕方については、以下のサイトを参照しました。 qiita.com
[Springboard.swift]
//// Springboard.swift//import XCTest import Foundation classSpringboard:XCTestCase { staticletshared= Springboard() letspringboard= XCUIApplication(bundleIdentifier:"com.apple.springboard") /** Terminate and delete the app via springboard */funcdeleteApp() { XCUIApplication().terminate() // Force delete the app from the springboardleticon= springboard.icons["【アプリ名】"] if icon.exists { leticonFrame= icon.frame letspringboardFrame= springboard.frame icon.press(forDuration:1.3) // Tap the little "X" button at approximately where it is. The X is not exposed directly springboard.coordinate(withNormalizedOffset:CGVector(dx: (iconFrame.minX +3) / springboardFrame.maxX, dy: (iconFrame.minY +3) / springboardFrame.maxY)).tap() // Wait for showing alertletalert= springboard.alerts["Delete “【アプリ名】”?"] letalertExists= NSPredicate(format:"exists == true") expectation(for:alertExists, evaluatedWith:alert, handler:nil) waitForExpectations(timeout:5, handler:nil) springboard.alerts.buttons["Delete"].tap() XCUIDevice.shared.press(.home) } } }
テストで使用する便利関数
XCUITestでも、ユーザー操作による画面上のレスポンスを待機する必要があります。 そこで、ユーザー操作を待ち合わせる、拡張関数を事前に定義しておきます。 [Extension.swift]
//// Extension.swift//import XCTest import Foundation extensionXCUIElement { functapIfExists(timeout:Double=10) { ifself.waitForExistence(timeout:timeout) { self.tap() } } funclazyTap(time:uint=1){ sleep(time) self.tap() } functype(text:String) { self.tap() self.typeText(text) } }
テストコード本体
それでは、テストファイルを記述していきます。 自前で用意した拡張関数を利用して、画面操作後の待機を行いテストを進行させます。システム通知への操作は、「springboard」を利用してUIテストを継続していきます。 [hogehogeUITests.swift]
//// hogehogeUITests.swift//import XCTest import Foundation classhogehogeUITests:XCTestCase { privateletapp= XCUIApplication() overridefuncsetUp() { // Put setup code here. This method is called before the invocation of each test method in the class.super.setUp() // In UI tests it is usually best to stop immediately when a failure occurs. continueAfterFailure =false// Delete the old application. Springboard().deleteApp() // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. app.launch() } overridefunctearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class.super.tearDown() app.terminate() } functest_foo() { // Use recording to get started writing UI tests.// Use XCTAssert and related functions to verify your tests produce the correct results.// Click after finding elements which contains texts "ほげほげ". app.buttons["ほげほげ"].tap() // Enter texts"ふが" in an element which contains texts "ぴよ".// Allow notifications form system. XCUIApplication(bundleIdentifier:"com.apple.springboard").buttons["Allow"].tapIfExists() } }
筆休め
Swiftでもリグレッションテスト向けの自動化されたITテスト用意しておくことで、コストが低く効果が高いテストを行えます。 アプリの品質が、事業の成否となる場面もあるので、しっかりとしたテストを行っておきたいですね。
以上、「XCUITestでUIテストを自動化する」でした。