Install any skill in seconds. Free to start, no credit card required.
Get Started Free →MCP (dart-mcp + Marionette) を使ったFlutterアプリのE2E自動化・UI検証ガイド。シミュレーターでのUI動作確認、モックプレビュー検証、Bridge経由のE2Eテスト、スクリーンショット撮影など、アプリの動作検証が必要なときに使う。「動作確認して」「UIを検証して」「E2Eテスト」「シミュレーターで確認」「モックで確認」と言われたときや、UI変更後の検証フェーズで使用すること。
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 91% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 117% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 334% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 200% | 0% |
| case-18 | ✗→✓ | ▲ Improved | 95% | 0% |
dart-mcp と Marionette MCP を使ったFlutterアプリのUI検証・E2E自動化ガイド。
特別な指示がない限り、以下をデフォルトとして使う:
flutter devices で確認し、iPhone Simulator を選択)8766(テスト用。本番の8765と分離してテストできる)git rev-parse --show-toplevel で取得)<プロジェクトルート>/apps/mobileユーザーが実機やポート8765を指定した場合はそちらに従う。
E2E検証は e2e-verifier サブエージェント に委譲すると効率的。独立したコンテキストで検証するため、実装バイアスなく客観的に動作を確認できる。
Agent tool で e2e-verifier サブエージェントを起動:
subagent_type: e2e-verifier
プロンプト:
---
アプリが起動済みです。以下の検証を実施してください。
## 検証内容
[検証したい項目を記述]
## 接続情報
- VM Service URI: [wsUri]
- PID: [pid]
日本語で回答してください。
---使い分け:
e2e-verifier サブエージェントに委譲bashflutter devices
出力からシミュレーターのデバイスIDを確認する(例: 1A2B3C4D-5E6F-...)。
mcp__dart-mcp__launch_app
root: <アプリルートの絶対パス>
target: lib/main.dart
device: <シミュレーターのデバイスID>返り値の pid を控える(以降の全ステップで必要)。
5秒待機する。 Xcodeビルド + シミュレーターへのデプロイが完了するまで待つ必要がある。初回ビルド時は10秒程度かかることもある。
mcp__dart-mcp__get_app_logs
pid: <Step 2のpid>ログ出力から app.debugPort イベントを探し、wsUri を抽出する:
json"params": { "wsUri": "ws://127.0.0.1:XXXXX/YYYY=/ws" }
wsUri が見つからない場合はビルドがまだ完了していない。5秒待って再度 get_app_logs を呼ぶ。
mcp__marionette__connect
uri: <wsUri>Marionette MCP は自動接続しないため、この手動 connect が必須。省略するとその後のUI操作が全て失敗する。
mcp__marionette__get_interactive_elementsUI要素の一覧が返れば接続成功。
原則: DTD/VM Service接続が必要な操作はMCP、それ以外はCLI
MCP が必要な操作はアプリのランタイムに接続して情報を取得・操作するもの(起動、停止、ホットリロード、UI操作、ログ取得など)。一方、ビルドツールや静的解析のようにアプリのランタイムに依存しない操作はCLIの方が速くて確実。
| 操作 | ツール | MCP名 | |------|--------|-------| | アプリ起動 | Dart MCP | launch_app | | アプリ停止 | Dart MCP | stop_app | | アプリログ取得 | Dart MCP | get_app_logs | | DTD接続 | Dart MCP | connect_dart_tooling_daemon | | ホットリロード | Dart MCP | hot_reload | | ホットリスタート | Dart MCP | hot_restart | | ウィジェットツリー | Dart MCP | get_widget_tree | | ランタイムエラー | Dart MCP | get_runtime_errors | | VM Service接続 | Marionette | connect | | UI要素一覧 | Marionette | get_interactive_elements | | タップ | Marionette | tap | | ダブルタップ | Marionette | double_tap | | 長押し | Marionette | long_press | | テキスト入力 | Marionette | enter_text | | スワイプ/ドラッグ | Marionette | swipe | | ピンチズーム | Marionette | pinch_zoom | | 戻る操作 | Marionette | press_back_button | | スクロール | Marionette | scroll_to | | アプリログ | Marionette | get_logs | | スクリーンショット | Marionette | take_screenshots | | カスタム拡張一覧 | Marionette | list_custom_extensions | | カスタム拡張呼び出し | Marionette | call_custom_extension |
| 操作 | コマンド | |------|---------| | デバイス一覧 | flutter devices | | テスト実行 | cd apps/mobile && flutter test | | 静的解析 | dart analyze apps/mobile | | フォーマット | dart format apps/mobile | | 依存関係 | cd apps/mobile && flutter pub get |
UI検証時は以下の順序で使う。スクリーンショットはトークンを大量に消費するため、テキストベースの検証を優先する:
get_interactive_elements — 最優先。画面上のタップ可能なボタン・入力欄の一覧を取得。画面遷移後は必ずこれを呼んで現在の状態を確認するget_logs — エラー確認。"ERROR", "Exception" でフィルタして問題がないか確認tap / enter_text / scroll_to — 基本UI操作。key指定を優先し、textやcoordinatesは代替手段double_tap / long_press / swipe / pinch_zoom / press_back_button — ジェスチャー系。通常操作で足りないときに使うlist_custom_extensions / call_custom_extension — アプリ固有の拡張操作。画面遷移ショートカットや内部トグル向けtake_screenshots — 最後の手段。レイアウトやビジュアルの確認が本当に必要な場合のみ。1セッションで3-5枚を目安に各画面のインタラクティブ要素に付与されたValueKey。tap や enter_text では key 指定が最も確実。
session_list — セッション一覧ListViewsearch_field — セッション検索入力search_button — 検索トグルボタンmock_preview_button — モックシナリオギャラリーを開く (AppBar)gallery_button — ギャラリー画面へ遷移refresh_button — セッション一覧リフレッシュdisconnect_button — サーバー切断new_session_fab — 新規セッション作成FABload_more_button — セッション追加読み込みserver_url_field — サーバーURL入力api_key_field — APIキー入力connect_button — 接続ボタンscan_qr_button — QRスキャンボタンmessage_input — メッセージテキスト入力send_button — メッセージ送信voice_button — 音声入力stop_button — ストリーミング停止slash_command_button — スラッシュコマンドメニューapprove_button — ツール実行承認reject_button — ツール実行拒否approve_always_button — Always承認モードview_plan_header_button — プランヘッダー表示plan_feedback_input — プランフィードバック入力clear_context_chip — コンテキストクリアチップcopy_button — メッセージコピーplain_text_toggle — プレーンテキスト表示切替share_button — メッセージ共有plan_edited_badge — プラン編集済みバッジview_full_plan_button — プラン詳細シート表示plan_edit_toggle — プラン編集モード切替plan_edit_field — プラン編集テキスト入力plan_edit_cancel — プラン編集キャンセルplan_edit_apply — プラン編集適用dialog_project_path — プロジェクトパス選択dialog_permission_mode — パーミッションモード選択dialog_worktree — Worktreeトグルdialog_worktree_branch — Worktreeブランチ入力dialog_start_button — セッション開始ボタンstatus_indicator — ステータスインジケーターsession_switcher — セッション切替Bridge Server なしでUIの見た目と挙動を確認できる。AppBarの「Mock Preview」ボタンから10種のモックシナリオにアクセスできる。
1. アプリ起動 (上記ワークフロー)
2. get_interactive_elements → ホーム画面の要素確認
3. tap key: "mock_preview_button" → モックギャラリーを開く
4. tap text: "<シナリオ名>" → 目的のシナリオを選択
5. get_interactive_elements → チャットUIの要素確認
6. get_logs → エラーがないか確認| # | 名前 | 検証ポイント | |---|------|-------------| | 1 | Approval Flow | approve/reject/always_approve ボタン表示 | | 2 | AskUserQuestion | 質問テキスト + 選択肢オプション表示 | | 3 | Multi-Question | 複数質問の同時表示 + multiSelect | | 4 | Image Result | 画像参照のツール結果表示 | | 5 | Streaming | 文字単位のストリーミング表示 | | 6 | Thinking Block | 折りたたみ可能な思考コンテンツ | | 7 | Plan Mode | EnterPlanMode → ExitPlanMode フロー | | 8 | Subagent Summary | Taskツール + 圧縮結果表示 | | 9 | Error | エラーメッセージ表示 | | 10 | Full Conversation | System → Assistant → Tool → Result 全体 |
クイックテスト推奨: Approval Flow, Streaming, Plan Mode(主要UIパターンをカバー)
Bridge Server を経由して実際のClaude Code / Codexセッションでの動作を検証する。
bash# Step 1: テスト用 Bridge 起動(ポート8766、本番8765に影響なし) cd <プロジェクトルート> && BRIDGE_PORT=8766 npm run bridge & # Step 2: アプリ起動(上記「アプリ起動ワークフロー」に従う) # Step 3: サーバー接続 # get_interactive_elements で接続フォームを確認 # enter_text key: "server_url_field" text: "ws://localhost:8766" # tap key: "connect_button" # Step 4: セッション作成 # tap key: "new_session_fab" # dialog_project_path でパスを選択 # tap key: "dialog_start_button" # Step 5: メッセージ送信 & 検証 # enter_text key: "message_input" text: "<テスト用プロンプト>" # tap key: "send_button" # get_interactive_elements で応答UIを確認 # 承認バーが表示されたら approve/reject の動作を検証 # Step 6: クリーンアップ # mcp__dart-mcp__stop_app (pid指定) # lsof -ti :8766 | xargs kill
get_interactive_elements で現在表示中の要素を確認scroll_to で画面外のウィジェットを表示させるget_logs でスタックトレースを確認stop_app → launch_app で再起動tap: key > text > coordinates の優先順位で指定する。keyが最も安定enter_text: key パラメータでテキストフィールドを指定するget_logs: Marionette接続後のログのみ取得。起動時のログは get_app_logs (dart-mcp) で取得hot_reload: UIの微調整に便利。ただしconst定義の変更やdependency更新には hot_restart が必要long_press: InkWell.onLongPress や GestureDetector.onLongPress に繋がる。CC Pocket の recent/running session card では長押しでアクションシートを開けるlong_press の検証対象は実画面を優先する。ストアスクリーンショット用のモック Session List は onLongPressRecentSession / onLongPressRunningSession が no-op のため、長押し挙動の確認には使えないswipe: Slidable と Dismissible の両方で有効。CC Pocket では recent session card のアーカイブ action pane 表示や、Git画面の stage / unstage / revert に使えるswipe 実行後は必ず get_interactive_elements を再取得して、action pane が開いたか、対象セルが横移動したかを確認するcopy_resume_command のような機能は、長押しでシートが出ること、対象項目をタップできること、シートが閉じることをもってUIフロー確認とするSlidable の key が要素一覧に出るので、swipe(key: "recent_session_<id>", direction: "left") のように key 指定で狙うのが安定get_interactive_elements で bounds を確認し、long_press(coordinates: {x, y}) を使うと成功率が高いlaunch_app: root は絶対パスで指定。返り値のPIDは必ず保存するlist_devices: 起動中のデバイスのみ表示されるstop_app: launch_app で取得したPIDを渡す検証完了後は必ずリソースを解放する:
1. mcp__dart-mcp__stop_app (pid指定) → アプリ停止
2. Bridge実行中なら: lsof -ti :8766 | xargs kill → テスト用Bridge停止Other measured skills in the registry, with their headline benchmark lift.