Claude Media
Claude CodeでMaestroのモバイルE2Eテストを書く — 画面を見せて直す

Claude CodeでMaestroのモバイルE2Eテストを書く — 画面を見せて直す

MaestroのMCPサーバーをClaude Codeに接続し、YAMLフローを書かせてシミュレータで実行し、失敗した画面を見せて直す手順です。日本語入力など先に知っておく制限も扱います。

MaestroのE2Eテストは、YAMLのフローを書いてシミュレータやエミュレーターで動かす形式です。Claude Codeに任せる場合の要点は、フローを書かせるだけで終わらせず、実機の画面を見せて直させる反復まで組むことです。

MaestroはCLIにMCPサーバーを同梱しており、Claude Codeから画面の構造を読み、フローを流し、結果で直せます。この記事は接続から、規約の置き方、反復の回し方、日本語アプリで先に知っておく制限までを順に扱います。

なぜMaestroはClaude Codeに任せやすいのか

Maestroはアプリを外から操作するブラックボックス型のツールです。アクセシビリティツリー(スクリーンリーダーが読むデータ層)と端末レベルの入力で動くため、アプリのソースや内部APIに触れません。

任せやすい理由は3つあります。

  • テストがYAMLの宣言で、Claudeが書く対象が小さい
  • アプリ側にテスト用の依存を足さない。Androidはbuild.gradleへ依存を足さず、テスト用APKも作らないとドキュメントにあります
  • 画面の構造を取得する手段が用意されており、推測でセレクタを書かずに済む

Appiumのセッション設定とロケータを書かせる手順はClaude CodeでAppiumのモバイルE2Eテストを書くにあります。Appiumが実機なしで確かめられる範囲を線引きする記事だったのに対し、Maestroはシミュレータを動かしながら直す前提で組みます。

準備 — Java 17以上とMaestro CLI

MaestroのMCPサーバーはCLIに同梱されています。先にCLIを入れます。前提はJava 17以上で、JAVA_HOMEがその場所を指している必要があります。既知の問題のページでは、Java 17か21を勧めています。

java -version
curl -fsSL "https://get.maestro.mobile.dev" | bash
maestro --help

macOSではHomebrewでも入れられます。iOSシミュレータを使うならXcodeとコマンドラインツールが要ります(xcode-select --install)。Windowsは公式のリリースページからzipを取り、PATHを通します。WSLは設定が増えるため、他の環境が使えるなら避けるよう書かれています。

MaestroのMCPサーバーをClaude Codeに足す

Claude Codeへの登録は1行です。

claude mcp add maestro -- maestro mcp

--より前がClaude Code側の引数、後ろがMCPサーバーとして起動するコマンドです。チームで共有するなら--scope projectを付けると、リポジトリの.mcp.jsonに書かれます。Maestroのバージョンを上げたときは、セッション内で/mcpを開いてmaestroを選び、Reconnectを押すと新しいバイナリを読み直します。

接続したら、Claude Codeが使えるツールは次の9つです。

ツール役割
list_devices役割使えるエミュレーター、シミュレータ、Chromiumの一覧
inspect_screen役割現在の画面の階層をJSONで返す
take_screenshot役割画面のスクリーンショット
run役割フローを実行する。YAMLの直接指定、ファイル、ディレクトリのいずれか
cheat_sheet役割コマンドと書式の早見表
list_cloud_devices役割Maestro Cloudで使える機種とOSの組
run_on_cloud役割フローをMaestro Cloudへ送る
get_cloud_run_status役割クラウド実行の状態確認
open_maestro_viewer役割画面を埋め込むViewerのURL

クラウド系の3つはMaestro Cloudの認証が必要で、maestro loginかAPIキー(MAESTRO_CLOUD_API_KEY)を用意します。ローカルのシミュレータで回すだけなら使いません。

権限は読み取りと実行で分ける

inspect_screenやtake_screenshotは画面を読むだけです。一方runは端末を実際に操作します。Maestroは設定アプリや通知のようなアプリ外にも触れるため、実行側は都度確認にしておくほうが安心です。許可の書き方はmcp__<サーバー名>__<ツール名>で、.claude/settings.jsonには次のように書けます。

{
  "permissions": {
    "allow": [
      "mcp__maestro__list_devices",
      "mcp__maestro__inspect_screen",
      "mcp__maestro__take_screenshot",
      "mcp__maestro__cheat_sheet"
    ]
  }
}

runを許可に入れなければ、フローを流すたびに確認が出ます。慣れてきたらmcp__maestro__runを足して、確認を外せます。

実行の様子はViewerで見る

MCPにはMaestro Viewerが付いています。シミュレータ、エミュレーター、実機の画面をWebアプリとして埋め込み、MCPが実行しているコマンドをリアルタイムで表示します。Claude Codeに「maestro viewerを開いて」と頼むと、open_maestro_viewerがURLを返します。

Claudeがどのコマンドを流し、画面のどこで止まったかを目で追えるため、失敗の原因を人が確かめたいときに役立ちます。見ているだけでなく、埋め込まれた端末を直接操作することもできます。

CLAUDE.mdにフローの規約を書いておく

Claudeは何も指定しないと、見えている文言をそのままセレクタにしがちです。多言語対応のアプリでは、文言が変わるとテストが壊れます。ドキュメントの方針に沿って、規約を先に置きます。

## Maestroフロー規約
- フローは `.maestro/` に置き、`appId: ${APP_ID}` で書く(Android/iOSでIDが違うため)
- セレクタは画面に出る文言を第一候補にする。多言語対応の画面、アイコン、画像は `id` を使う
- 固定の `sleep` や座標タップは書かない。待つ必要は `extendedWaitUntil` で書く
- ログイン済みの状態が要るフローは、共通のログインフローを `runFlow` で呼ぶ
- 書いたら必ず `inspect_screen` で要素を確認し、`run` で実行して結果を見る
- フローには `tags` を付ける(`smoke` など)

Maestroは待機を自動で行います。assertVisibleは要素がすぐ見つからなくても約7秒は待って再試行します。それ以上かかる画面だけ、extendedWaitUntilでタイムアウトを延ばします。

フローを書かせて、画面を見せて直す

反復は次の流れで回します。

手順

書いて、動かして、直すまで

  1. 1

    画面を読ませる

    アプリを立ち上げた状態で、inspect_screenの結果をもとにフローを書かせます。要素の名前を想像で書かせないためです。

  2. 2

    短いフローを1本だけ流す

    最初はログインなど1画面分のフローをrunで実行します。長いフローを一度に流すと、どこで失敗したか追いにくくなります。

  3. 3

    失敗したら画面をもう一度読む

    失敗した直後のinspect_screenとtake_screenshotを見せます。画面が想定と違えば、セレクタか遷移を直します。

  4. 4

    通ったら次の画面へ

    通ったフローは保存し、次の画面を足します。共通部分はrunFlowで別ファイルに切り出します。

依頼の文面は、完了条件を実行結果に置きます。

.maestro/login.yaml にログイン成功までのフローを書いてください。
1. inspect_screen で今の画面の要素を確認する
2. セレクタは id があれば id、なければ画面の文言にする
3. run で実行し、失敗したら inspect_screen と take_screenshot を見て直す
4. 通るまで繰り返し、通ったら使ったセレクタの一覧を報告する

出来上がるフローは、例えば次のような形になります(公式のコマンド仕様に沿った例です)。

appId: ${APP_ID}
tags:
  - smoke
---
- launchApp:
    clearState: true
- tapOn:
    id: "email_input"
- inputText: "test@example.com"
- tapOn:
    id: "password_input"
- inputText: "password123"
- tapOn:
    id: "login_button"
    enabled: true
- assertVisible: "ホーム"

launchAppのclearState: trueは、アプリのデータを消してから起動します。前回の状態が残ってテストが揺れるのを防ぎます。enabled: trueを付けたタップは、ボタンが押せる状態になるまで待ってから実行されます。

実行はMCP経由でなくても、同じフローをCLIで確かめられます。

maestro test -e APP_ID=com.example.app .maestro/login.yaml

-eで渡した値が、フロー内の${APP_ID}に入ります。AndroidとiOSでアプリのIDが違うときは、この値を切り替えるだけで同じフローを使い回せます。

アプリ側で用意するもの — セレクタの足場

Claudeがうまくセレクタを書けるかは、アプリ側の識別子で決まります。ここは人が整えます。

  • React Native: testIDがMaestroのidに対応します。文言より安定するため、公式もこちらを勧めています
  • Flutter: Textなどは文言で取れます。アイコンのように文言がない部品はsemanticLabelを付けます。Flutter 3.19以降はSemanticsのidentifierで、言語に依存しないIDを渡せます。FlutterのKeyはアクセシビリティ層に出ないため、Maestroからは見えません
  • SwiftUI / UIKit: アクセシビリティの識別子を付けるとidで取れます

Claudeに識別子を足す変更も任せるなら、「testIDが無い要素に追加してからフローを書く」と順番を指定すると、フローとアプリ側の両方が揃います。

Expo Goで開発している場合は、launchAppにカスタムのappIdを使えません。openLinkで開発用のURLを開く書き方になります。

先に知っておく制限 — 日本語入力とiOSのキーボード

Claudeが日本語のテストデータを書いた場合に気づけるよう、規約にも一行足しておくと確実です。

- Androidで実行するフローの `inputText` はASCIIだけにする(日本語は使えない)

iOSには別の注意があります。

  • hideKeyboardはiOSで確実にキーボードを閉じられません。公式は、見出しなどキーボードの外の要素をtapOnする代替を挙げています
  • ページングで追加読み込みするUITableViewやUICollectionViewは、XCTestの不具合で想定外のタイミングで読み込みが走ることがあります

アプリが起動しないときは、appIdの取り違えを疑います。Androidはadb shell pm list packages、iOSシミュレータはxcrun simctl listapps bootedでIDを確かめられます。

タグで絞ってCIに載せる

MCPを使わず、Claudeにファイルを編集させて人がCLIで確かめる運用もあります。その場合はmaestro test -c(--continuous)で連続モードにしておくと、フローの保存ごとに再実行されるため、編集と確認を往復しやすくなります。

フローが増えたら、tagsで実行範囲を分けます。

maestro test .maestro/ --include-tags=smoke --format=JUNIT \
  --test-output-dir=./maestro-report

--format=JUNITでCIが読めるレポートを出し、--test-output-dirにスクリーンショットなどの成果物を集めます。サブフォルダのフローを実行対象に含めるには、config.yamlのflowsにグロブを書く必要があります。フォルダを指定しただけでは、直下のファイルしか実行されません。

Claude Codeに「テストが通るまで止めない」運用を組み合わせるなら、agent hookで完了条件を検証させる手順が使えます。MCPの追加やスコープの考え方はClaude CodeのMCPサーバー設定ガイドにまとまっています。複数の機種で並列に流したいときは、Maestro Cloudの出番です。

任せる範囲のまとめ

Maestroは画面の構造を読めるので、Claude Codeに任せる範囲が広がります。フローの記述、セレクタの選定、失敗時の修正は任せられます。

人が決めるのは、アプリ側の識別子、Androidで日本語を入力するかどうか、runを自動許可にするかどうかです。この3つを先に決めておくと、反復が安定します。

この記事を共有:XはてブLinkedIn