mcpField
X
xcuitest-skill

xcuitest-skill

github.com/lambdatestテスト・品質384240 回インストール2 週間前に更新
リポジトリ

xcuitest-skill について

xcuitest-skillは、iOS QAエンジニア向けのXCUITest自動化ガイドです。Swiftのテストパターンに加え、ローカルシミュレーターとTestMu AIクラウドでの実行方法を扱います。

主な機能

  1. 01Swiftテストと要素クエリ
  2. 02タップ、入力、ジェスチャー操作
  3. 03アサーションとシステムアラート処理
  4. 04ページオブジェクトとアンチパターン
  5. 05ローカルおよびTestMu AIクラウドでの実行

活用シーン

  1. 01iOSログイン画面のテスト
  2. 02UI要素の待機と検証
  3. 03権限アラートの処理
  4. 04Xcodeまたはコマンドラインからのテスト実行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/lambdatest/agent-skills --skill xcuitest-skill

インストール後、Claude Code で/xcuitest-skillを入力して読み込まれたか確認します。

同梱ファイルreference/advanced-patterns.mdreference/playbook.md

詳細

XCUITest 自動化スキル

あなたは XCUITest を専門とするシニア iOS QA エンジニアです。

ステップ 1 — 実行ターゲット

├─ Mentions "cloud", "TestMu", "LambdaTest", "device farm"?
│  └─ TestMu AI cloud (upload IPA + test runner)
│
├─ Mentions "simulator", "local", "Xcode"?
│  └─ Local: Xcode Test Navigator or xcodebuild
│
└─ Default → Local simulator

基本パターン — Swift

基本的なテスト
import XCTest

class LoginTests: XCTestCase {
    let app = XCUIApplication()

    override func setUpWithError() throws {
        continueAfterFailure = false
        app.launch()
    }

    func testLoginWithValidCredentials() {
        let emailField = app.textFields["emailInput"]
        XCTAssertTrue(emailField.waitForExistence(timeout: 5))
        emailField.tap()
        emailField.typeText("[email protected]")

        let passwordField = app.secureTextFields["passwordInput"]
        passwordField.tap()
        passwordField.typeText("password123")

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

        let dashboard = app.staticTexts["Welcome"]
        XCTAssertTrue(dashboard.waitForExistence(timeout: 10))
    }

    func testLoginWithInvalidCredentials() {
        app.textFields["emailInput"].tap()
        app.textFields["emailInput"].typeText("[email protected]")
        app.secureTextFields["passwordInput"].tap()
        app.secureTextFields["passwordInput"].typeText("wrong")
        app.buttons["loginButton"].tap()

        let error = app.staticTexts["Invalid credentials"]
        XCTAssertTrue(error.waitForExistence(timeout: 5))
    }
}
要素の検索
// By accessibility identifier (best)
app.buttons["loginButton"]
app.textFields["emailInput"]

// By label text
app.staticTexts["Welcome back"]
app.buttons["Submit"]

// By predicate
app.buttons.matching(NSPredicate(format: "label CONTAINS 'Login'")).firstMatch

// By index
app.cells.element(boundBy: 0)

// Existence check
let element = app.buttons["submit"]
XCTAssertTrue(element.waitForExistence(timeout: 10))
操作
element.tap()                           // Tap
element.doubleTap()                     // Double tap
element.press(forDuration: 2)           // Long press
element.typeText("hello")              // Type (field must be focused)
element.swipeUp()                       // Swipe
element.swipeDown()
element.swipeLeft()
element.swipeRight()
element.pinch(withScale: 2, velocity: 1)  // Zoom in
element.rotate(CGFloat.pi, withVelocity: 1) // Rotate
アサーション
XCTAssertTrue(element.exists)
XCTAssertTrue(element.isHittable)
XCTAssertTrue(element.isEnabled)
XCTAssertEqual(element.label, "Expected Label")
XCTAssertEqual(element.value as? String, "Expected Value")
XCTAssertTrue(element.waitForExistence(timeout: 10))
システムアラートの処理
// Auto-handle permission dialogs
addUIInterruptionMonitor(withDescription: "Permission Alert") { alert in
    if alert.buttons["Allow"].exists {
        alert.buttons["Allow"].tap()
        return true
    }
    return false
}
app.tap() // Trigger the monitor
ページオブジェクトパターン
protocol Page {
    var app: XCUIApplication { get }
}

class LoginPage: Page {
    let app: XCUIApplication

    init(app: XCUIApplication) { self.app = app }

    var emailField: XCUIElement { app.textFields["emailInput"] }
    var passwordField: XCUIElement { app.secureTextFields["passwordInput"] }
    var loginButton: XCUIElement { app.buttons["loginButton"] }
    var errorLabel: XCUIElement { app.staticTexts["errorMessage"] }

    func login(email: String, password: String) -> DashboardPage {
        emailField.tap()
        emailField.typeText(email)
        passwordField.tap()
        passwordField.typeText(password)
        loginButton.tap()
        return DashboardPage(app: app)
    }
}
アンチパターン
悪い例良い例理由
sleep(5)waitForExistence(timeout:)信頼性に欠けます
待機せずに要素を検索するまず必ず waitForExistence を実行する競合状態を防げます
タップ座標をハードコードするアクセシビリティ識別子を使う画面サイズは異なるためです
1 つの巨大なメソッドでテストする小さく焦点を絞ったテストメソッドを使う分離性が向上します
TestMu AI Cloud
# 1. Create .ipa from Xcode: Product → Archive → Distribute → Ad Hoc
# 2. Upload app and test runner
curl -u "$LT_USERNAME:$LT_ACCESS_KEY" \
  -X POST "https://manual-api.lambdatest.com/app/upload/realDevice" \
  -F "[email protected]" -F "type=ios"

curl -u "$LT_USERNAME:$LT_ACCESS_KEY" \
  -X POST "https://manual-api.lambdatest.com/app/upload/realDevice" \
  -F "[email protected]" -F "type=ios"

# 3. Execute on real devices
curl -u "$LT_USERNAME:$LT_ACCESS_KEY" \
  -X POST "https://mobile-api.lambdatest.com/framework/v1/xcui/build" \
  -H "Content-Type: application/json" \
  -d '{
    "app": "lt://APP123",
    "testSuite": "lt://TEST456",
    "device": ["iPhone 16-18", "iPhone 15 Pro-17"],
    "build": "XCUITest Cloud Build",
    "video": true, "deviceLog": true
  }'

クイックリファレンス

タスクコマンド
Xcode から実行⌘U または Product → Test
CLI から実行xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 16'
特定のテストを実行xcodebuild test -only-testing:MyAppUITests/LoginTests/testLogin
スクリーンショットlet screenshot = XCUIScreen.main.screenshot()
添付ファイルlet attachment = XCTAttachment(screenshot: screenshot)
起動引数app.launchArguments = ["--uitesting"]
起動環境変数app.launchEnvironment = ["ENV": "test"]

高度なパターン

高度なパターン、デバッグガイド、CI/CD との統合、ベストプラクティスについては、 reference/playbook.md を参照してください。

コメント