[SwiftUI] [UnitTest] [Xcode] Xcode を使ったテストの始め方
Sponsor Link
テスト環境&対象
- macOS Catalina 10.15.7
- Xcode 12.1
- SwiftUI で作られたアプリケーション
- SwiftUI Text コンポーネント
テスト項目
テスト設計は非常に重要です。何をしたら、どうなる。
Text は、非常にシンプルな要素なので、ここでは、「何が表示されているか」をテスト対象とします。
アプリケーションのライフサイクルで特に変化せず、常に同一テキストが表示されている想定で、何が表示されているかをテストするものとします。
今回は、サンプルのプロジェクトを作成すると表示される Hello, world! が表示されているかを確認します。
UnitTest / UITest
Xcode での test には、おおきく2種類あります。 UnitTest と UITest です。
UnitTest は、アプリケーションの機能確認用のテストを書くためのもので、アプリケーションを関数レベルでテストすることに使用されます。
UITest は、アプリケーションの動作を UI (User interface) を経由して確認するテストで、実際のユーザーが行うような操作を行い、期待通り動作するかを確認するテストに使用されます。
Xcode の プロジェクト作成時に “include Tests” にチェックを入れると、Unit Test と UI Test の2つが作成されます。
これらのテストは、プロジェクトに追加された2つのターゲット <プロジェクト名>Tests と <プロジェクト名>UITests として確認することができます。
今回は、Text コンポーネントの動作を、アプリケーションの外側から確認するので、UITest の一部として実行されるテストを作成することになります。
UITest テンプレート
UITest 向けには、以下のようなコードがテンプレートとして生成されます。
//
// TDDTextUITests.swift
//
// Created by : Tomoaki Yagishita on 2020/10/27
// © 2020 SmallDeskSoftware
//
import XCTest
class TDDTextUITests: XCTestCase {
// (1)
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
// (2)
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
// (3)
func testExample() throws {
// UI tests must launch the application that they test.
let app = XCUIApplication()
app.launch()
// Use recording to get started writing UI tests.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
// (4)
func testLaunchPerformance() throws {
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) {
// This measures how long it takes to launch your application.
measure(metrics: [XCTApplicationLaunchMetric()]) {
XCUIApplication().launch()
}
}
}
}
以下のような関数が定義されています。
- (1) setupWithError 関数
- テスト1つ1つの実行前にこの関数が実行されます。テストの前提条件を整える等に使われます
- (2) tearDownWithError 関数
- テスト1つ1つの実行後にこの関数が実行されます。テスト実行後の後処理等に使われます
- (3) testExample 関数
- テストコードのサンプルです。この関数では、アプリケーションを起動するところまでがサンプルとして記述されています
- (4) testLaunchPerformance 関数
- アプリケーションの起動時間のパフォーマンスをテストするコードのサンプルです。この記事では説明しません。
testLabelValue
testExample をベースとして、ラベルの値をテストする testLabelValue を書いてみます。
func testLabelValue() throws {
// UI tests must launch the application that they test.
let app = XCUIApplication()
app.launch()
// (1)
let text = app.staticTexts["TextHelloWorld"]
// (2)
XCTAssertTrue(text.exists)
// (3)
XCTAssertEqual(text.label, "Hello, world!")
}
- アプリケーションから、ID “TextHelloWorld” を持つテキストを検索します
- 検索してきたテキストが存在するかをテストします
- テキストのラベルが、”Hello, world!” であるかをテストします
上記のテストを成功させるためには、アプリケーションコード側にも変更が必要です。
Accessibility ID
非常に小さく簡単なテストですが、要素をどのように取得してくるかが、このテストのポイントです。
アプリケーション中の要素は、XCUIElementQuery を使用して探すことができます。
Apple のドキュメントは、こちら。
XCUIApplication も 親クラスである XCUIElement が、XCUIElementTypeQueryProvider に準拠しているために使用できます。
App.staticTexts で、アプリケーション中の Text を取得することができます。ただし、全ての Text を取得できてしまうので、その中から該当する Text を指定する必要があります。
そこで使用されるのが、accesibility の ID です。この ID を使用して、特定の Text を取得することができます。
SwiftUI では、.accessibility modifier を使って、この ID を指定することができます。
UIKit では、Storyboard 上で指定することもできました。
以下は、今回のテスト用に、accessibility modifier を追加したコードです。
//
// ContentView.swift
//
// Created by : Tomoaki Yagishita on 2020/10/27
// © 2020 SmallDeskSoftware
//
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello, world!")
.padding()
.accessibility(identifier: "TextHelloWorld")
// (1)
}
}
- accessibility modifier を使用して、Text に “TextHelloWorld”という ID を付与
Text のラベル
取得できた Text のラベル値は、label プロパティで取得できます。
Hello, world! であることのテストは、以下のようなコードになります。
XCTAssertEqual(text.label, "Hello, world!")
まとめ:SwiftUI の Text をテストする
- XCUIApplication から、accessibility ID 指定で Text を取得することができる
- XCUIApplication からは、staticTexts[“ID”] で Text を取得することができる
- Text のラベルは、label プロパティで取得できる
- SwiftUI では、accessibility ID は、.accessibility modifier で付与する
- XCTAssert でテストする
説明は以上です。
不明な点やおかしな点ありましたら、ご連絡いただけるとありがたいです。
Sponsor Link