Playwright MCP で E2E テストを作ろうとしたらうまくいかなかった話
0. はじめに
CursorとPlaywright MCP と組み合わせれば“簡単に E2E が書ける”らしい
そんな噂を検証すべく、社内にE2Eテストの知見がなくいいチャンスだったので試してみたらCursorのトークンを1日で大量に消費しうまく動かなかった話です。
弊社では宅配クリーニングのサイトを運営しており、そのうちの2つでチャレンジしてみました。
対象ページ | 特徴 |
---|---|
React SPA | 衣類クリーニングの注文フォーム |
PHP SSR | 保管クリーニングの注文フォーム |
1. React SPA — 118 トークン溶かしても動かず
まずは、SPAの自社のメインのサービスの注文フォームで試してみました。
AIへの指示文
my.lenet.jp/orderにアクセスして注文完了まで完了するE2Eテストを作成してください。
サイトの構造はPlaywright MCPを使用して確認してください。
入力が必要な箇所は以下のパターンに合わせてください
預ける方法は自宅から
預ける日は選択できる
最短日を選択 預け時間は選択できる最短時間を選択
受取日・受け取り時間は自動で選択されるので未選択
オプションは未選択
その他ご要望は未選択
こちらも一緒にいかがですか?は未選択
クーポンコードは未入力
エラーが出たらエラーメッセージを見て対応する動作を都度考えて行なってください。
以上で確認画面へ行き注文完了へ
上記の内容を行うE2Eテストコードを作成する
項目 | 状況 |
---|---|
生成サイクル | 3 回(計 118 トークン)すべて同じ locator を出力 |
実行結果 | 静的ページのログインは成功 → 注文フォームで即タイムアウト |
MCP の挙動 | カレンダーコンポーネントを理解できず、セルをすべて同じ <td> と認識。 |
固有属性も role も拾えず locator('text="1"') などテキスト一致を乱発 → 前月セルと競合してクリック失敗 |
🔍 原因
最大のつまずきは、固定セレクターがほぼ無いカレンダーでした。
Playwright MCP は innerText しか頼れないため、セルを locator('text="1"')
などテキスト一致で指定するコードを生成。
生成自体は「完了」と判定されましたが、実際に実行すると
- 前月セルを誤クリック
- 「次へ」ボタンが有効化されず先へ進めない
-
strict mode violation
が連発してタイムアウト
という状況に陥り、見かけ上はテストが書けたのに動かない という結果になりました。
問題のカレンダー
🩹 応急対応
- <td>1</td>
+ <td data-testid="cal-2025-07-01">1</td>
-
data-testid
を 追加
data-testid をカレンダーのセルの要素に追加しただけで、MCP が
getByTestId('cal-2025-07-01') を提案。
その結果 日付クリック できるようになったが、トークン使用量が多すぎるためここまでで断念
保管クリーニングの注文フォーム
— エラーログ貼り付けで動いた
2. PHP SSR AIへの指示文
@https://my.lenet.jp/trial_order/cloak
にアクセスして注文完了まで完了するE2Eテストを作成してください。
サイトの構造はPlaywright MCPを使用して確認してください。
入力が必要な箇所は以下のパターンに合わせてください
お名前 テスト太郎
フリガナ テストタロウ
電話番号 09012341234
メールアドレス ランダムな値@example.com
パスワード 123456
郵便番号 1000000 郵便番号入力後住所検索ボタンを押すこと
住所は自動入力なので何もしない
番地・建物名 1-1-1
お洋服の返却先住所 初期入力のまま
ご希望のお洋服の返却時期 初期入力のまま
お支払い方法 代金引換
クーポンコード 初期入力のまま
試行 | 所要ステップ | 結果 |
---|---|---|
初回生成 | 1 プロンプト | label-for 完備でほぼ一発ヒット |
1 回目実行 | エラー箇所 4 行 |
strict mode violationのエラーログ を貼って再生成 |
2 回目実行 | ボタン文言 1 行手直し | MCP が存在しない文言を提案 → 次へ進む に変更 |
3 回目実行 | 完了 | 約 45 秒 で最終画面まで到達 |
なぜ少ない修正で済んだ?
- 直近でフォームのリファクタリングを行なっており、すべての
<input>
に<label for>
が付与 →getByRole
/getByLabelText
がそのまま使えた
3. 成功と失敗を分けたもの
比較軸 | React SPA |
data-testid 追加後 |
PHP SSR |
---|---|---|---|
固定セレクター | 無し | あり (3) | ラベル+for 完備 |
MCP 出力 | 変化せず同じ locator | 新しい locator を自動生成 | そのまま使用可 |
手動修正 | なし | なし(testid 追加のみ) | ボタン文言 1 行 |
フロー完走 | ×(ログインのみ) | △(クリックまで) | ○(45 秒) |
肝は “セレクター”
AIが認識しやすいHTML構造を作っていくのが今後の課題として残った
4. 今後の方針 ― “AI が迷わないフォーム” づくり
-
まずは UI 要素に一意な識別子を付ける
- カレンダーの日付セルや主要ボタン、入力欄など “テストで触る場所” すべてに汎用的な
data-testid
を付与。 - 具体的な命名規則はチーム内ガイドラインで統一し、実装とテストを切り離す。
- カレンダーの日付セルや主要ボタン、入力欄など “テストで触る場所” すべてに汎用的な
-
ラベル & アクセシビリティ属性を徹底
-
<label>
と<input>
のペアや、aria-*
属性で状態を公開。 - これにより role / name ベースでも要素が特定できる。
-
さいごに
ホワイトプラスでは、ビジョンやバリューに共感していただけるエンジニアを募集しています!
ネットクリーニングの「リネット」など、「生活領域×テクノロジー」で事業を展開しています。
弊社に興味がある方は、オウンドメディア「ホワプラSTYLE」をご覧ください。オンラインでのカジュアル面談も可能ですので、ぜひお気軽にお問い合わせください。
Discussion