【SwiftUI】初めてのUITest

# はじめに
最近、テストを書くようになりました。
そんなこともあり、ちょっと調べたので今の知識をまとめておきます。

# テストメソッド
```swift
// ✅: なし
// ❌: 必ず失敗
XCTFail(value)

// ✅: value = nil (valueがnil)
// ❌: value ≠ nil (valueがnilじゃない)
XCTAssertNil(value)

// ✅: value ≠ nil (valueがnilじゃない)
// ❌: value = nil (valueがnil)
XCTAssertNotNil(value)

// ✅: value = true (valueがtrue)
// ❌: value ≠ true (valueがtrueじゃない)
XCTAssert(value)

// ✅: value = true (valueがtrue)
// ❌: value ≠ true (valueがtrueじゃない)
XCTAssertTrue(value)

// ✅: value = false (valueがfalse)
// ❌: value ≠ false (valueがfalseじゃない)
XCTAssertFalse(value)

// ✅: value1 = value2 (value1とvalue2が等しい)
// ❌: value1 ≠ value2 (value1とvalue2が等しくない)
XCTAssertEqual(value1, value2)

// ✅: value1 > value2 (value1がvalue2より大きい)
// ❌: value1 ≦ value2 (value1がvalue2以下)
XCTAssertGreaterThan(value1, value2)

// ✅: value1 ≧ value2 (value1がvalue2以上)
// ❌: value1 < value2 (value1がvalue2より小さい)
XCTAssertGreaterThanOrEqual(value1, value1)

// ✅: value1 < value2 (value1がvalue2より小さい)
// ❌: value1 ≧ value2 (value1がvalue2以上)
XCTAssertLessThan(value1, value2)

// ✅: value1 ≦ value2 (value1がvalue2以下)
// ❌: value1 > value2 (value1がvalue2より大きい)
XCTAssertLessThanOrEqual(value1, value2)
```

https://zenn.dev/lsk4f5/articles/abad25e1583500


# テストの作り方
初期のテストコードです。
コメントは削除してます。

関数名を`test`から始めるとテストとして認識されるらしいです。
```diff_swift
import XCTest

class UITest_DemoUITests: XCTestCase {

    override func setUpWithError() throws {
        continueAfterFailure = false
    }

    override func tearDownWithError() throws {

    }

    func testExample() throws {
        let app = XCUIApplication()
        app.launch()
    }

+   func testSample() {
+
+   }

    func testLaunchPerformance() throws {
        if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
            measure(metrics: [XCTApplicationLaunchMetric()]) {
                XCUIApplication().launch()
            }
        }
    }
}

```

# アプリの起動
`XCUIApplication().launch()`で起動可能です。
```diff_swift
func testSample() {
+   let app = XCUIApplication()
+   app.launch()
}
```

# 待機時間を設定する
`sleep(3)`で3秒待機します。
```diff_swift
func testSample() {
    let app = XCUIApplication()
    app.launch()

+   sleep(3)
}
```

# UIコンポーネントの取得
## UI側
`accessibility`でidentifierを設定する事で簡単にUITest側から取得する事ができます
```diff_swift
        Button("アラートの表示(Button)") {
            isButton = true
        }
+       .accessibilityIdentifier("button")
```
## UITest側
```diff_swift
func testSample() {
    let app = XCUIApplication()
    app.launch()

    sleep(3)

+   // ボタンの取得
+   let button = app.buttons["button"]
+   // ボタンのタップ
+   button.tap()
}
```

`accessibility`を設定せずに`descendants(matching: )`や`children(matching: )`で取得することも可能ですが結構めんどくさいです。

# TextField関係
入力と削除をしてます。
```swift
func testInputTextField() {
    let app = XCUIApplication()
    // アプリ起動
    app.launch()
    // 3秒待機
    sleep(3)
    // テキストフィールドの取得
    let textfield = app.textFields["textfield"]
    // テキストフィールドのタップ
    textfield.tap()
    // 1秒待機
    sleep(1)
    // テキストフィールドに入力
    textfield.typeText("自動でテキストフィールドに入力します。")
    // 3秒待機
    sleep(3)
    // 現在入力されている文字を取得
    guard let text = textfield.value as? String else { return }
    // 取得した文字数分削除ボタンを押す
    let delete = String(repeating: XCUIKeyboardKey.delete.rawValue, count: text.count)
    // 削除
    textfield.typeText(delete)
    // 3秒待機
    sleep(3)
}
```

# Button関係
```swift
func testButton() {
    let app = XCUIApplication()
    // アプリ起動
    app.launch()
    // 3秒待機
    sleep(3)
    // ボタンの取得
    let button = app.buttons["button"]
    // ボタンのタップ
    button.tap()
    // 3秒待機
    sleep(3)
}
```

# Text関係
ここで詰まりました
SwiftUIには`Button`以外に`onTapGesture`というタップイベントをつけられるものがあります。
これをボタン判定だと思って時間を無駄にしました笑
```swift
func testText() {
    let app = XCUIApplication()
    // アプリ起動
    app.launch()
    // 3秒待機
    sleep(3)
    // テキストの取得
    let text = app.staticTexts["text"]
    // テキスト(onTapGesture)のタップ
    text.tap()
    // 3秒待機
    sleep(3)
}
```

# 画面回転
```swift
// ホームボタンが下
XCUIDevice.shared.orientation = .portrait

// ホームボタンが上
XCUIDevice.shared.orientation = .portraitUpsideDown

// ホームボタンが左
XCUIDevice.shared.orientation = .landscapeLeft

// ホームボタンが右
XCUIDevice.shared.orientation = .landscapeRight
```

# 設定ごとにテスト
```swift
// 画面の向き、言語設定、外観設定ごとにテスト
override class var runsForEachTargetApplicationUIConfiguration: Bool {
    true
}
```



# おわり
随時更新していきます