mcpField
M
maestro-mobile-testing

maestro-mobile-testing

github.com/tovimxテスト・品質281.2k 回インストール37 週間前に更新
リポジトリ

maestro-mobile-testing について

Maestro Mobile E2E Testingは、モバイルアプリのE2Eテストを宣言型YAMLで作成するためのスキルです。再利用可能なフロー、セレクター、認証パターン、スクリプト作成を案内し、さまざまなUI状態の検証に役立ちます。

主な機能

  1. 01宣言型YAMLテストフロー
  2. 02自動待機と組み込みリトライ
  3. 03再利用可能なサブフローとセレクター
  4. 04GraalJSによるJavaScriptスクリプト
  5. 05認証とUI状態テストのガイド

活用シーン

  1. 01再現可能なモバイルスモークテストの作成
  2. 02ログインとOTPフローのテスト
  3. 03認証状態ごとのUI動作の検証
  4. 04モックサーバーを使ったAPI依存画面のテスト

インストール

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

$npx skills add https://github.com/tovimx/maestro-mobile-testing-skill --skill maestro-mobile-testing

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

詳細

Maestro モバイル E2E テスト

概要

Maestro は、宣言型の YAML ベースのモバイル E2E テストフレームワークです。自動待機、組み込みのリトライロジック、そしてボイラープレートなしの高速実行を提供します。React Native アプリでは、Detox や Appium よりも安定しています。

主な機能
  • 宣言型 YAML — 命令型のテストコードは不要、ステップを書くだけ
  • 自動待機 — 手動の sleep() や不安定な待機は不要
  • 組み込みのリトライ — テストの不安定性を軽減
  • 高速実行 — セットアップのオーバーヘッドなしで素早く実行
  • Maestro Studio — インタラクティブなテストビルダー(maestro studio)
  • サブフロー — DRY なテストのための再利用可能な YAML シーケンス
  • JavaScript スクリプティング — HTTP 呼び出しやデータ操作のための GraalJS ランタイム
  • Maestro Cloud — ローカルシミュレーターなしで CI 上で実機テスト

クイックスタート

インストール
curl -Ls "https://get.maestro.mobile.dev" | bash
brew install openjdk@17
export JAVA_HOME=/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home
最小限のテスト
appId: com.myapp
---
- launchApp
- tapOn:
    id: "my-button"
- assertVisible: "Expected Text"
実行
maestro test .maestro/smoke-test.yaml
maestro test --debug .maestro/smoke-test.yaml  # step through
maestro studio                                  # interactive builder

コアパターン

1. セレクター戦略: testID とテキストの比較

セレクターのアプローチはプロジェクトの状況に応じて選択してください。どちらも有効であり、適切な選択はアプリが多言語対応かどうか、そしてチームのテスト方針によって決まります。

状況推奨されるセレクター理由
多言語 / i18nid:(testID)翻訳に対して安定
単一言語テキストラベル人間が読みやすく、自己文書化されたテスト
エージェントが保守するテストどちらでも — 開発者に確認AI が保守するフローでは可読性の重要度は低い
システムダイアログテキスト(常に)ネイティブのアラートでは testID は使用不可
# testID selector — stable across translations
- tapOn:
    id: "submit-button"

# Text selector — human-readable, self-documenting
- tapOn: "Submit"

testID を優先すべき場合:

  • アプリが複数の言語をサポートしている、または翻訳される予定がある
  • UI のテキストが動的、または頻繁に変更される
  • 複数の要素が同じ表示テキストを共有している

テキストセレクターを優先すべき場合:

  • 文言が安定した単一言語のアプリ
  • 可読性と自己文書化が優先される
  • ユーザーに表示される動作を、表示されているとおりに正確にテストする

React Native では、ID ベースのセレクターを使用する場合に testID プロパティを追加します。

<TouchableOpacity testID="submit-button" onPress={handleSubmit}>
  <Text>{t('submit')}</Text>
</TouchableOpacity>
testID の命名規則

ID ベースのセレクターを使用する場合:

{component}-{action/type}[-{variant}]

Examples:
- auth-prompt-login-button
- product-card-{id}
- otp-input-0
- tab-home
- dashboard-loading
2. 認証プリフライトパターン

Maestro が認証状態の解決前に UI を操作してしまう競合状態を防ぎます。認証の読み込みが完了したときにのみレンダリングされる、サイズゼロの auth-loaded マーカーを追加します。

// In your tab bar or root layout
{!isLoading && <View testID="auth-loaded" style={{ width: 0, height: 0 }} />}

そして、すべてのテストで:

- launchApp

# Prevent XCTest crash on cold boot (iOS)
- swipe:
    direction: DOWN
    duration: 100

# Wait for auth state to resolve
- extendedWaitUntil:
    visible:
      id: "auth-loaded"
    timeout: 15000

# Now safe to interact
- tapOn:
    id: "tab-home"
3. 適応型テスト(両方の認証状態を処理)

テストは、ユーザーが認証済みかどうかに関係なく動作する必要があります。

# Auth flow — only runs if login prompt is visible
- runFlow:
    when:
      visible: "Sign In"
    file: flows/auth-flow.yaml

# Already authenticated — proceed directly
- runFlow:
    when:
      visible:
        id: "tab-home"
    file: flows/authenticated-action.yaml
4. 楽観的更新のテスト

短いタイムアウトを使用して、サーバーの応答より前に UI の変更が発生することを検証します。

# Trigger mutation
- tapOn:
    id: "action-button"

# OPTIMISTIC: UI must change within 3s (not waiting for server)
- extendedWaitUntil:
    visible:
      id: "undo-button"
    timeout: 3000

# Verify derived UI state
- extendedWaitUntil:
    visible:
      id: "user-indicator"
    timeout: 5000
アクション期待される変化タイムアウト
ミューテーションのトリガーボタンの状態が切り替わる< 3s
リストの更新項目が表示/非表示になる< 5s
アクションの再実行永続性を証明< 3s
5. ネイティブアラートの閉じ方

React Native の Alert.alert() は、UI をブロックするネイティブダイアログを生成します。

- tapOn:
    id: "action-button"

# Wait for expected state change first
- extendedWaitUntil:
    visible:
      id: "new-state-element"
    timeout: 5000

# Dismiss alert (optional in case it already closed)
- tapOn:
    text: "OK"
    optional: true

# Brief delay for alert animation
- swipe:
    direction: DOWN
    duration: 300
6. 再利用性のためのサブフロー

繰り返されるシーケンスをサブフローファイルに分割します。

.maestro/
├── flows/
│   ├── auth-and-return.yaml
│   ├── complete-purchase.yaml
│   └── verify-result.yaml
├── smoke-test.yaml
└── feature-test.yaml
# In main test
- runFlow:
    file: flows/auth-and-return.yaml
7. ディープリンク(Expo)

バンドル ID ではなく、app.json の Expo スキームを使用します。

# WRONG
- openLink: "com.myapp://profile/settings"

# CORRECT
- openLink: "myapp://profile/settings"

ディープリンクは、アプリのディープリンクハンドラーに登録されている必要があります。登録されていないルートはサイレントに失敗します。

8. プラットフォーム固有のロジック
- runFlow:
    when:
      platform: ios
    file: flows/ios-specific.yaml

- runFlow:
    when:
      platform: android
    file: flows/android-specific.yaml
9. 環境変数
appId: com.myapp
env:
  TEST_EMAIL: [email protected]
  API_BASE_URL: http://localhost:3000
---
- inputText: ${TEST_EMAIL}
10. セレクターの状態プロパティ

enabled、selected、checked、focused を使用して、要素を現在の状態でターゲットにします。これは、アクションの前後にインタラクティブな要素の状態を検証するのに便利です。

# Only tap the submit button if it's enabled
- tapOn:
    id: "submit-button"
    enabled: true

# Assert a checkbox is checked
- assertVisible:
    id: "terms-checkbox"
    checked: true

# Wait for an input to be focused
- extendedWaitUntil:
    visible:
      id: "email-input"
      focused: true
    timeout: 3000
プロパティ値ユースケース
enabledtrue / false送信中、またはフォームが有効になるまで無効化されるボタン
checkedtrue / falseチェックボックス、トグルスイッチ
selectedtrue / falseタブ項目、セグメント化コントロール
focusedtrue / false自動フォーカスされる入力フィールド
11. 相対位置セレクター

類似した要素を、他の要素との空間的な関係によって区別します。これはインデックスベースの選択よりも慣用的で、耐性があります。

# BAD — fragile, breaks if order changes
- tapOn:
    text: "Add to Basket"
    index: 1

# GOOD — contextual, self-documenting
- tapOn:
    text: "Add to Basket"
    below:
      text: "Awesome Shoes"

利用可能な相対セレクター:

# Target element below another
- tapOn:
    text: "Buy Now"
    below: "Product Title"

# Target element that is a child of a parent
- tapOn:
    text: "Delete"
    childOf:
      id: "item-card-42"

# Target a parent that contains a specific child
- tapOn:
    containsChild: "Urgent"

# Target by multiple descendants
- tapOn:
    containsDescendants:
      - id: title_id
        text: "Specific Title"
      - "Another descendant text"

# Horizontal positioning
- tapOn:
    text: "Edit"
    rightOf: "Username"
セレクター意味
below:要素が参照要素の下に位置する
above:要素が参照要素の上に位置する
leftOf:要素が参照要素の左にある
rightOf:要素が参照要素の右にある
childOf:要素が参照親の直接の子である
containsChild:要素が参照に一致する直接の子を含む
containsDescendants:要素が指定されたすべての子孫要素を含む

認証テスト

アーキテクチャ

E2E で OTP またはマジックリンク認証をテストするには、プログラムによってメールを取得する必要があります。一般的なパターン:

┌─────────────┐     ┌──────────────┐     ┌─────────────────┐
│  Maestro    │────▶│  Auth        │────▶│  Email Capture  │
│  Test       │     │  Provider    │     │  Service        │
└─────────────┘     └──────────────┘     └─────────────────┘
       │                                        │
       │         ┌──────────────────────────────┘
       │         ▼
       │   ┌─────────────┐
       └──▶│  REST API   │ ─── GET /api/v1/messages
           │  (email)    │ ─── Extract OTP code
           └─────────────┘

一般的なメール取得サービス: Mailpit、MailHog、Ethereal。

OTP 取得スクリプト

Maestro の GraalJS ランタイムを使用して、メール取得サービスから OTP コードを取得します:

// CRITICAL: Maestro uses GraalJS — NO async/await, NO fetch()
var email = typeof EMAIL !== "undefined" ? EMAIL : "[email protected]";
var emailServiceUrl = typeof EMAIL_SERVICE_URL !== "undefined"
  ? EMAIL_SERVICE_URL : "http://localhost:8025";

var response = http.get(emailServiceUrl + "/api/v1/messages");
if (!response.ok) {
  throw new Error("Failed to fetch emails: " + response.status);
}

var data = json(response.body);
// Find the latest email and extract OTP code
var body = data.messages[0].Content.Body;
var match = body.match(/(\d{6})/);
output.OTP_CODE = match[1];
OTP 入力戦略

自動フォーカスする OTP コンポーネントでは、各桁を個別に入力する必要があります。入力する前に各入力欄をタップします:

# Split OTP into digits via helper script
- runScript:
    file: scripts/split-otp.js
    env:
      OTP_CODE: ${output.OTP_CODE}

# Enter each digit by tapping its input
- tapOn:
    id: "otp-input-0"
- inputText: ${output.OTP_0}

- tapOn:
    id: "otp-input-1"
- inputText: ${output.OTP_1}
# ... repeat for all digits

プロバイダー固有の実装 (Supabase + Mailpit、Firebase Auth、Auth0) については、これを拡張するプロジェクトレベルのスキルを作成してください。


GraalJS スクリプトのルール

Maestro は GraalJS ランタイムを使用します。これらの制約は絶対です:

機能状態
async/awaitサポートされていません
fetch()サポートされていません
http.get()、http.post()代わりにこれらを使用してください
json()レスポンスボディの解析に使用します
output.VARYAML フローで使用する変数を設定します
var 宣言必須 (安全性のため const/let ではなく var を使用してください)
// Script template
var response = http.get("http://localhost:8025/api/endpoint");
if (!response.ok) {
  throw new Error("Request failed: " + response.status);
}
var data = json(response.body);
output.RESULT = data.value;

重要な落とし穴

clearState は iOS キーチェーンをクリアしません

clearState: true はアプリのサンドボックス (UserDefaults、ファイル、キャッシュ) をクリアしますが、iOS キーチェーンはクリアしません。expo-secure-store (またはキーチェーンベースのストレージ) 経由で保存された認証トークンは、clearState リセット後も、さらにはアプリの再インストール後も保持されます。

# WRONG — user may still be authenticated
- launchApp:
    clearState: true
- assertVisible: "Welcome"  # Fails if Keychain has tokens

# CORRECT — wait for auth resolution, then adapt
- launchApp
- extendedWaitUntil:
    visible:
      id: "auth-loaded"
    timeout: 15000

ルール:

  • iOS でゲスト状態を生成するために clearState に依存しないでください
  • 認証テストの場合: clearState をスキップし、auth-loaded プレフライトを使用してください
  • ゲストテストの場合: 両方の状態を処理するアダプティブフローを使用してください
  • clearState の後にゲスト専用 UI をアサートしないでください

注意: Android では、clearState: true は認証情報を含むアプリデータを完全にリセットします。これは iOS のみの落とし穴です。

XCTest kAXErrorInvalidUIElement クラッシュ (iOS)

コールドブートで最初のレンダリングサイクルが完了する前に Maestro がアクセシビリティツリーと相互作用すると、XCTest ドライバーがクラッシュする可能性があります。

修正: launchApp の直後に no-op スワイプを追加します:

- launchApp
- swipe:
    direction: DOWN
    duration: 100
API サーバーへの依存

localhost のバックエンド API を呼び出すモバイルアプリには、完全なサーバーまたはモックサーバーが実行されている必要があります。これがないと、API に依存するすべての画面にローディングスピナーまたは空の状態が表示されます (クエリはサイレントに失敗します)。

修正: Maestro テストを実行する前にモック API サーバーを起動します:

# Start mock server (serves canned responses on your API port)
npx tsx scripts/mock-api-server.ts &

# Then run tests
maestro test .maestro/my-test.yaml

アプリが呼び出す各エンドポイントに対して定型の JSON を返す軽量なモックを作成してください。これは完全なバックエンドを実行するよりも高速で、より決定論的です。

認証対応タブバー

ゲストと認証済みユーザーで異なるタブを表示するタブバーは、セレクターの失敗を引き起こします:

状態一般的なタブ
ゲストhome、search、cart、profile
認証済みhome、feed、create、messages、profile

両方の状態に存在するタブのみをアサートするか、アダプティブな when: 条件を使用してください。


テストファイルテンプレート

# {Feature} {Action} Test
#
# Tests: {what this validates}
# Prerequisites:
# - Simulator/emulator running with app installed
# - Backend or mock server running (if API-dependent)

appId: com.myapp
env:
  TEST_EMAIL: maestro-{feature}@example.com
  EMAIL_SERVICE_URL: http://localhost:8025
---
# ==========================================
# STEP 1: LAUNCH + AUTH PRE-FLIGHT
# ==========================================

- launchApp

- swipe:
    direction: DOWN
    duration: 100

- extendedWaitUntil:
    visible:
      id: "auth-loaded"
    timeout: 15000

- takeScreenshot: 01-initial-state

# ==========================================
# STEP 2: {ACTION}
# ==========================================

- tapOn:
    id: "target-element"

# ==========================================
# STEP 3: VERIFY
# ==========================================

- extendedWaitUntil:
    visible:
      id: "expected-result"
    timeout: 5000

- takeScreenshot: 02-final-state

フォルダ構成

.maestro/
├── README.md                    # Quick reference + testID inventory
├── config.yaml                  # Shared configuration
├── flows/                       # Reusable sub-flows
│   ├── auth-and-return.yaml
│   ├── complete-action.yaml
│   └── verify-result.yaml
├── scripts/                     # GraalJS helpers
│   ├── fetch-otp.js
│   └── split-otp.js
├── smoke-test.yaml              # Guest navigation
├── auth-signin.yaml             # OTP sign-in flow
├── feature-screenshots.yaml     # Screenshot capture flows
└── feature-action.yaml          # Feature-specific tests

scripts/
├── mock-api-server.ts           # Lightweight mock for E2E
└── run-e2e.sh                   # Orchestration script
命名規則
種類パターン例
メインテスト{feature}-{action}.yamlcheckout-purchase.yaml
サブフロー{action}-{context}.yamlauth-and-return-to-dashboard.yaml
スクリプト{verb}-{noun}.jsfetch-otp.js

インフラストラクチャ

API 依存テスト用のモックサーバー

API レイヤーに対して定型レスポンスを返す軽量なモックサーバーを作成します。これは、E2E テスト中に完全なバックエンドを実行するよりも高速で、より確実です。

# Start mock server before running Maestro tests
npx tsx scripts/mock-api-server.ts &
オーケストレーションスクリプト

シェルスクリプトで E2E のセットアップ全体を自動化します。スクリプトは以下を行います。

  1. バックエンドサービス(データベース、認証)を起動する
  2. テストデータを投入する
  3. モック API サーバーを起動する
  4. Maestro テストを実行する
  5. すべてのサービスをクリーンアップする
bash scripts/run-e2e.sh
シードデータ

特定のデータに依存するテストには、シード済みのデータベースが必要です。シードスクリプトはテストインフラストラクチャのそばに置き、各テストスイートの前に実行してください。


Android 固有のパターン

エミュレーターのセットアップ

Android のテストには、エミュレーターまたは USB 接続された実機が必要です。Maestro は接続されたデバイスを自動検出します。

# List available system images
sdkmanager --list | grep system-images

# Create emulator
avdmanager create avd -n maestro_test \
  -k "system-images;android-34;google_apis;arm64-v8a"

# Start emulator
emulator -avd maestro_test
iOS と Android の違い
項目iOSAndroid
デバイスの種類シミュレーターのみ(実機不可)エミュレーター + ADB 経由の実機
clearStateKeychain をクリアしませんアプリデータを完全にリセットします
コールドブート時のクラッシュXCTest kAXError(スワイプ遅延を追加)同等の問題はありません
パフォーマンスネイティブで動作(高速)ARM エミュレーション(x86 では低速)
権限ダイアログシステムアラートテキストが異なるシステムダイアログ
ADB によるデバッグ
adb devices                                    # List connected devices
adb shell am start -n com.myapp/.MainActivity  # Launch app
adb logcat | grep Maestro                      # Filter Maestro logs
adb shell input keyevent 82                    # Unlock screen
Android の権限処理

Android の権限はシステムダイアログとして表示されます。オプションのタップで閉じます。

- tapOn:
    text: "Allow"
    optional: true

- tapOn:
    text: "While using the app"
    optional: true

CI/CD 連携

Maestro Cloud を使用した GitHub Actions

Maestro Cloud は、ローカルシミュレーターなしで CI 内に実機を提供します。公式アクションを使用してください。

name: Mobile E2E Tests
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  maestro-e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Build Android APK
      - uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Build Android APK
        run: |
          cd apps/mobile
          npx expo prebuild --platform android --no-install
          cd android && ./gradlew assembleRelease

      - name: Run Maestro Cloud Tests
        id: maestro
        uses: mobile-dev-inc/action-maestro-cloud@v2
        with:
          api-key: ${{ secrets.MAESTRO_API_KEY }}
          app-file: apps/mobile/android/app/build/outputs/apk/release/app-release.apk
          workspace: .maestro
          include-tags: ci

      # Access results
      # ${{ steps.maestro.outputs.MAESTRO_CLOUD_CONSOLE_URL }}
      # ${{ steps.maestro.outputs.MAESTRO_CLOUD_UPLOAD_STATUS }}
      # ${{ steps.maestro.outputs.MAESTRO_CLOUD_FLOW_RESULTS }}
タグベースのフローフィルタリング

タグを使用して、CI とローカルのどちらでどのテストを実行するかを制御します。

# In your flow file header
appId: com.myapp
tags:
  - ci
  - smoke
---
- launchApp
# ... test steps
# Run only CI-tagged flows locally
maestro test --include-tags ci .maestro/

# Exclude work-in-progress flows
maestro test --exclude-tags wip .maestro/
Docker を使用したローカル CI(Android のみ)
FROM openjdk:17-slim

RUN curl -Ls "https://get.maestro.mobile.dev" | bash
ENV PATH="/root/.maestro/bin:${PATH}"

COPY .maestro/ /app/.maestro/
WORKDIR /app

CMD ["maestro", "test", ".maestro/"]

Note: iOS のテストは Docker では実行できません(macOS が必要です)。CI での iOS には Maestro Cloud を使用してください。


Maestro Cloud

Maestro Cloud は、ローカルシミュレーターのセットアップなしで実機上でテストを実行します。

セットアップ
  1. cloud.maestro.dev でアカウントを作成する
  2. ダッシュボードから API キーを生成する
  3. CI プロバイダーの MAESTRO_API_KEY シークレットとして保存する
CLI からの実行
# Upload and run on Maestro Cloud
maestro cloud --api-key $MAESTRO_API_KEY \
  --app-file ./app-release.apk \
  .maestro/

# With tag filtering
maestro cloud --api-key $MAESTRO_API_KEY \
  --app-file ./app-release.apk \
  --include-tags smoke \
  .maestro/
重要なポイント
  • iOS テスト: Maestro Cloud でサポートされています(ローカルの実機では不可)
  • Android テスト: ローカルの実機と Maestro Cloud の両方
  • 結果: 動画録画、ログ、スクリーンショットを含むダッシュボード
  • CI 出力: MAESTRO_CLOUD_CONSOLE_URL、MAESTRO_CLOUD_FLOW_RESULTS

Maestro MCP サーバー

Maestro MCP サーバー は、Maestro のコマンドセット全体を Model Context Protocol ツールとして公開し、AI エージェントが YAML を書くだけでなく、テストを実行してデバイスと直接対話することを可能にします。

このスキルを補完する仕組み
このスキルMaestro MCP
役割正しいパターンを教える実行時環境を提供する
レイヤー作成(適切な YAML を書く)実行(実行、タップ、アサート、スクリーンショット)
出力より良いテストファイルライブデバイスとの対話

両方を併用してください。このスキルは AI が正しいテストを書くことを保証し、MCP はそれを即座に実行し、失敗を確認し、反復することを可能にします。

セットアップ

MCP は Maestro CLI に同梱されています — 追加のインストールは不要です。

# Verify it's available
maestro mcp

Claude Code — プロジェクトの .mcp.json またはグローバル設定に追加します。

{
  "mcpServers": {
    "maestro": {
      "command": "maestro",
      "args": ["mcp"]
    }
  }
}

Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json(macOS)に追加します。

{
  "mcpServers": {
    "maestro": {
      "command": "maestro",
      "args": ["mcp"]
    }
  }
}

Cursor、Windsurf、VS Code、JetBrains IDE でもサポートされています。IDE 固有のセットアップについては Maestro MCP ドキュメント を参照してください。

主な機能

MCP サーバーは、カテゴリ別に整理された 47 個のツールを公開しています:

カテゴリツール例
UI 操作タップ、スワイプ、スクロール、長押しtapOn、scrollUntilVisible
テキスト入力入力、削除、貼り付け、コピーinputText、eraseText
アサーション可視性、AI による検証assertVisible、assertWithAI
アプリのライフサイクル起動、停止、状態のクリアlaunchApp、clearState
デバイス制御位置情報、画面の向き、機内モードsetLocation、hideKeyboard
フロー制御フローの実行、繰り返し、スクリプトの評価runFlow、evalScript
メディアスクリーンショット、録画takeScreenshot、startRecording
AI による機能視覚的なアサーション、欠陥検出assertWithAI、assertNoDefectsWithAI
Write-Run-Fix ループ

このスキルと MCP の両方が有効な場合、AI は次のことができます:

  1. このスキルのパターンを使用してテスト YAML を 書く
  2. MCP の runFlow / launchApp と操作ツールを使ってそれを 実行する
  3. スクリーンショットとアサーションを通じて失敗を 確認する
  4. YAML を 修正 して再実行する — すべて 1 つの会話の中で

デバッグ

maestro test --debug .maestro/test.yaml   # Step through interactively
maestro record .maestro/test.yaml          # Record as video
maestro studio                             # Interactive UI builder
maestro hierarchy                          # View element tree

スクリーンショットは ~/.maestro/tests/{timestamp}/ に保存されます。


新しいテストのためのチェックリスト

[ ] Unique test email (maestro-{feature}@example.com)
[ ] Selector strategy chosen (testID for i18n apps, text for single-language — see Pattern 1)
[ ] Selectors use state properties where relevant (enabled, checked — see Pattern 10)
[ ] Similar elements distinguished with relative selectors, not index (see Pattern 11)
[ ] Auth pre-flight pattern used (auth-loaded)
[ ] Post-launch swipe added (iOS crash prevention)
[ ] Both auth states handled (adaptive flows)
[ ] Native alerts dismissed after mutations
[ ] Short timeouts for optimistic updates (3-5s)
[ ] Sub-flows created for reusable sequences
[ ] Descriptive screenshots at key points
[ ] Header comment with prerequisites
[ ] Added to README.md test table
[ ] Mock API server started if backend-dependent
[ ] Tags added for CI filtering (ci, smoke, wip)

よくあるエラー

エラー原因修正方法
「Unable to locate Java Runtime」Java が PATH にないexport JAVA_HOME=/opt/homebrew/opt/openjdk@17/...
タップ後に「Element not found」ネイティブのアラートがブロックしているtapOn: text: "OK" optional: true を追加する
OTP の数字が入力されない自動フォーカスの干渉個別の otp-input-N testID を使用する
テストは成功するが何も起こらないoptional: true の誤用optional は本当に任意のアクションにのみ使用する
可視性で「Assertion is false」要素がまだレンダリングされていないタイムアウトを増やすか、testID が存在するか確認する
スクリプトの出力が空JS API が間違っているfetch() ではなく http.get() を使用する
clearState 後に認証状態が不安定iOS のキーチェーンがクリアされていないclearState を使用せず、適応型フローを使用する
kAXErrorInvalidUIElement クラッシュコールドブートの競合(iOS)起動後のスワイプに遅延を追加する
ローディングスピナー / 空の画面API サーバーが実行されていないテストの前にモック API サーバーを起動する
権限ダイアログがブロックする(Android)システムダイアログが閉じられていないtapOn: text: "Allow" optional: true を追加する

リソース

コメント