AIはPlaywright開発の「最高の相棒」になるか?実践・プロンプト設計術でE2Eテストを劇的効率化
ChatGPT・Claude活用でテストコード生成を自動化 - 検証済みテンプレート&フォールバック戦略付き

前回の記事では、PlaywrightのセットアップからCI統合まで、モダンE2Eテストの全体像を解説しました。 テストコードが書けるようになった次のステップは 「いかに速く、質の高いテストを量産するか」 です。
そこで今回は、AIを活用してPlaywrightの開発効率を劇的に向上させるための、具体的なプロンプト設計術を紹介します。
実践前に知っておくべき重要なポイント ⚠️
AIプロンプト設計術を実際に適用する前に、以下の点を理解しておくことが重要です:
- APIモックとの協調が必要: AIが生成するテストコードは、非同期処理やタイミングの調整が必要になる場合があります
- 段階的な実装が推奨: 一度に全てを完璧に生成しようとせず、基本的な部分から段階的に構築することが現実的です
- フォールバック戦略が重要: セマンティックロケーターを優先しつつ、複数の選択肢を用意することで安定性が向上します
フォールバック戦略とは、メインの方法がダメだった時の「予備案」を用意しておくことです。
Webアプリは頻繁に更新されるため、テスト用の要素指定が突然使えなくなることがあります。例えば、開発初期には
<button data-testid="submit-btn">送信</button>
という要素があったのに、アップデート後に<button class="btn-primary">送信</button>
のようにdata-testidが削除されてしまうケースです。従来の単一指定方法では、この変更でテストが壊れてしまいます。そこでPlaywrightの.or()
を使って、複数の指定方法を用意するのがフォールバック戦略です。具体的には、
page.getByRole('button', { name: '送信' }).or(page.getByTestId('submit-btn')).or(page.locator('button.btn-primary'))
のように記述し、1番目の方法がダメでも2番目、3番目の方法で要素を見つけられるようにします。優先順位としては、まずgetByRole(ユーザーが実際に認識する方法で最も安定)、次にgetByTestId(テスト専用の識別子で中程度の安定性)、最後にCSSセレクター(見た目に依存し最も変更されやすい)の順番で指定するのが効果的です。
この戦略により、DOM構造が変更されてもテストが壊れにくくなり、メンテナンス工数が大幅に削減されます。まさに「転ばぬ先の杖」として機能する重要な手法です。
この記事で得られること
- AIを活用した テストコード生成の実務的な流れ
- 「情報不足な指示」と「改善された指示」の比較
- プロンプト設計次第でAI出力の質を大きく変えられることの理解
- AIを安全に活用するための注意点と、最終的に人間がレビューすべき観点
- 実践検証に基づいた現実的なアプローチ
AIに渡すべき情報の整理
AIにテストコード作成を頼むときの最大のコツは 「必要な情報を全部伝えること」 です。 情報が不足したまま依頼すると、曖昧なセレクタや一部のケースしか考慮されていない、中途半端なコードが返ってきます。
伝えるべき6つの情報
- 機能仕様: 正常系・異常系・境界値の条件
- 環境情報: ブラウザ、実行環境(ローカル/CI)など
- 対象要素の情報: HTML構造、ラベル、
data-testid
など - エラー状況: エラーメッセージ全文、発生頻度など
- 期待する観点:
getByRole
優先、Flaky対策など - APIモック設定: 成功・失敗レスポンスの詳細
⚠️ AIを使う際のセキュリティ注意点
AIにコードや仕様を渡す前に、必ず以下の点を確認してください。
- 本番環境の認証情報やAPIキーは絶対に含めない
- 顧客情報や機密性の高いビジネスロジックは抽象化して伝える(例:「ユーザーID: 123」→「ユーザーID:
some_user_id
」) - 可能であれば、セキュリティが担保された社内AIやローカルで動作するAIの活用も検討する
📝 実践検証済みテストケース設計用プロンプトテンプレート
毎回考えるのは大変なので、以下のテンプレートを活用してみてください。
[機能名]について、Playwrightでテストコードを生成してください。
【仕様】
- 正常系:[期待する動作を具体的に記述]
- 異常系:[エラー条件と期待する挙動を記述]
- 境界値:[上限・下限・特殊値での挙動を記述]
【要素指定とフォールバック戦略】
- [操作対象]: getByRole('[role]', { name: '[name]' }).or(getByTestId('[test-id]'))
- [確認対象]: getByTestId('[test-id]').or(locator('[css-selector]'))
【APIモック設定】
- [成功レスポンス]: { status: 200, body: { ... } }
- [エラーレスポンス]: { status: 400/500, body: { error: "..." } }
【待機戦略】
- アニメーション完了の確認方法
- 非同期データ読み込みの待機方法
【実行環境】
- ブラウザ:[Chromium/Firefox/WebKit]
- 実行場所:[ローカル/CI]
1. テストケース設計の支援
👎 不十分なプロンプト
ショッピングカートのテストを書いてください
👍 改良後のプロンプト
ECサイトのショッピングカート機能について、Playwrightでテストコードを生成してください。
観点: 正常系 / 異常系 / 境界値
【仕様】
- 正常系:「カートに追加」ボタンを押すと数量が+1される
- 異常系:在庫切れ商品は追加できない(APIは400を返す)
- 境界値:カートは10個まで。11個目でエラーメッセージ表示
【要素指定とフォールバック戦略】
- ボタン: getByRole('button', { name: 'カートに追加' }).or(getByTestId('add-to-cart'))
- 数量表示: getByTestId('cart-count').or(locator('.cart-counter'))
【APIモック設定】
- 成功: { status: 200, body: { count: 1, total: 1500 } }
- 在庫切れ: { status: 400, body: { error: "在庫切れです" } }
- 上限超過: { status: 400, body: { error: "カート上限に達しました" } }
✨ 改良後のAI出力例
test.describe('ショッピングカート機能', () => { test('正常系: 商品を追加できる', async ({ page }) => { await page.route('**/api/cart/add', route => { route.fulfill({ json: { count: 1, total: 1500 } }); }); await page.getByRole('button', { name: 'カートに追加' }).click(); await page.waitForResponse('**/api/cart/add'); await expect(page.getByTestId('cart-count')).toHaveText('1'); }); test('異常系: 在庫切れ商品の追加を防止する', async ({ page }) => { await page.route('**/api/cart/add', route => { route.fulfill({ status: 400, json: { error: "在庫切れです" } }); }); await page.getByRole('button', { name: 'カートに追加' }).click(); await expect(page.getByText('在庫切れです')).toBeVisible(); }); test('境界値: カート上限数を超えるとエラーを表示する', async ({ page }) => { // 上限超過のモックを設定 await page.route('**/api/cart/add', route => { route.fulfill({ status: 400, json: { error: "カート上限に達しました" } }); }); await page.getByRole('button', { name: 'カートに追加' }).click(); await expect(page.getByText('カート上限に達しました')).toBeVisible(); }); });
具体的な指示により、APIモック設定まで含めた実用的なテストコードを生成できます。
2. ロケーター生成の支援
👎 不十分なプロンプト
この画面要素をPlaywrightで確認したい
👍 改良後のプロンプト
以下のHTMLに基づき、保守性の高いPlaywrightロケーターを生成してください。
- getByRole や getByPlaceholder を優先
- DOM変更に強いセマンティックな指定を使用
- フォールバック戦略として .or() を活用
<div class="user-management-panel">
<h2 id="users-title">ユーザー管理</h2>
<button data-action="add-user" data-testid="add-user-btn">新規ユーザー追加</button>
<input type="text" placeholder="名前で検索" data-testid="search-input">
</div>
✨ 改良後のAI出力例
// セマンティックロケーター(推奨) await expect(page.getByRole('heading', { name: 'ユーザー管理' })).toBeVisible(); // フォールバック戦略付きロケーター const addButton = page .getByRole('button', { name: '新規ユーザー追加' }) .or(page.getByTestId('add-user-btn')) .or(page.locator('[data-action="add-user"]')); const searchInput = page .getByPlaceholder('名前で検索') .or(page.getByTestId('search-input')); await expect(addButton).toBeVisible(); await expect(searchInput).toBeVisible();
フォールバック戦略により、DOM変更に強い安定したロケーターが生成されます。
3. エラー分析・トラブルシューティング
👎 不十分なプロンプト
PlaywrightでモーダルをテストしたらTimeoutになりました。直してください。
👍 改良後のプロンプト
Playwrightでモーダルをテスト中にTimeoutErrorが出ます。
原因と改善策を踏まえ、安定したコードを生成してください。
【HTML抜粋】
<div class="modal fade-in-complete" id="confirmModal">
<button class="confirm-btn">削除を確認</button>
</div>
【エラーメッセージ】
TimeoutError: locator.click: Timeout 30000ms exceeded
【期待】
- モーダルが開き切ってから(fade-in-completeクラスが付与されてから)クリックする
- アニメーション時間は最大2秒
- 段階的な待機戦略を実装
✨ 改良後のAI出力例
test('モーダル操作の安定化', async ({ page }) => { // モーダルを開く await page.click('#open-modal'); // 段階的な待機戦略 const modal = page.locator('#confirmModal'); // Step 1: 基本的な表示待機 await expect(modal).toBeVisible(); // Step 2: アニメーション完了確認 await expect(modal).toHaveClass(/fade-in-complete/); // Step 3: 内部要素の操作可能確認 const confirmButton = modal.getByRole('button', { name: '削除を確認' }); await expect(confirmButton).toBeEnabled(); // Step 4: 安全な操作実行 await confirmButton.click(); });
段階的な待機戦略により、アニメーションに依存する要素でも安定してテストできます。
実装時によくある課題と対策 🛠️
APIモックと非同期処理の協調
よくある問題
// ❌ APIレスポンスとDOM更新のタイミングずれ await page.getByRole('button', { name: 'カートに追加' }).click(); await expect(page.getByTestId('cart-count')).toHaveText('1'); // Timeout発生
推奨対策
// ✅ API完了とDOM更新の両方を待機 await page.route('**/api/cart/add', route => { route.fulfill({ json: { count: 1 } }); }); await page.getByRole('button', { name: 'カートに追加' }).click(); await page.waitForResponse('**/api/cart/add'); await expect(page.getByTestId('cart-count')).toHaveText('1');
フォールバック戦略の実装
基本パターン
// セマンティック → TestID → CSS の優先順位 const submitButton = page .getByRole('button', { name: '送信' }) .or(page.getByTestId('submit-btn')) .or(page.locator('button[type="submit"]'));
複雑なフォーム処理
問題: フロントエンドバリデーションとAPIエラーの競合
// ✅ バリデーション完了を待ってからAPI処理 await page.fill('#email', 'invalid-email'); await page.getByRole('button', { name: '送信' }).click(); // フロントエンドエラーを確認 await expect(page.getByText('有効なメールアドレスを入力してください')).toBeVisible(); // 正しい値で再実行 await page.fill('#email', 'valid@example.com'); await page.getByRole('button', { name: '送信' }).click(); // API成功を確認 await expect(page.getByText('送信が完了しました')).toBeVisible();
よくある失敗パターンとデバッグ手法 🔍
1. タイミング関連の問題
症状: TimeoutError: locator.click: Timeout 30000ms exceeded
段階的デバッグ手順
const element = page.getByRole('button', { name: 'クリック' }); // Step 1: 要素の存在確認 await expect(element).toBeVisible(); // Step 2: アニメーション完了確認 await expect(element).toHaveClass(/animation-complete/); // Step 3: クリック可能状態確認 await expect(element).toBeEnabled(); // Step 4: 最終実行 await element.click();
2. APIモック設定の問題
症状: 期待したレスポンスが返らない
デバッグパターン
// リクエスト/レスポンスのログ出力 page.on('request', request => console.log('Request:', request.url())); page.on('response', response => console.log('Response:', response.status())); // モックの動作確認 await page.route('**/api/**', route => { console.log('Mock intercepted:', route.request().url()); route.fulfill({ json: { success: true } }); });
3. 要素が見つからない問題
診断用コード
// 現在のページ状態を確認 await page.screenshot({ path: 'debug.png' }); console.log('Current URL:', page.url()); console.log('Page title:', await page.title()); // 類似要素を検索 const similarElements = await page.locator('button').all(); for (const btn of similarElements) { const text = await btn.textContent(); console.log('Found button:', text); }
AIツールごとの実践的な使い分け 🤖
検証結果に基づく推奨用途
ChatGPT/Claude(対話型AI)
- ✅ 得意:テストケース設計、エラー分析、プロンプトテンプレート生成
- ✅ 適用場面:新機能のテスト戦略立案、複雑なエラーの原因分析
- ⚠️ 注意:APIモック設定は人間の調整が必要な場合が多い
GitHub Copilot(コーディング支援)
- ✅ 得意:既存コードパターンの再利用、ボイラープレート生成
- ✅ 適用場面:類似テストケースの量産、定型的なアサーション記述
- ⚠️ 注意:新しいパターンでは精度が下がる
実践的な併用パターン
- ChatGPT/Claudeでテスト設計とプロンプト作成
- GitHub Copilotで実装時のコード補完
- 人間による統合テストとデバッグ
推奨される開発フロー 🎯
段階的なアプローチ
-
基本テストケース生成
- AIでシンプルな正常系テストを生成
- ローカル環境で動作確認
-
エラーケース追加
- 異常系・境界値テストをAIで拡張
- APIモックとタイミング調整
-
安定性の改善
- フォールバック戦略の実装
- 待機戦略の最適化
-
CI環境での検証
- 環境依存の問題を特定・修正
- 継続的な品質維持
デバッグ時の基本戦略
test('デバッグ用テンプレート', async ({ page }) => { // 1. 現在状態の記録 await page.screenshot({ path: `debug-start.png` }); try { // 2. 操作実行 await page.getByRole('button', { name: 'テスト' }).click(); // 3. 結果確認 await expect(page.getByText('成功')).toBeVisible(); } catch (error) { // 4. エラー時の詳細記録 await page.screenshot({ path: `debug-error.png` }); console.log('Error occurred:', error.message); console.log('Current URL:', page.url()); throw error; } });
AIの限界と、人間が担うべき役割
AIは強力なアシスタントですが、万能ではありません。AIを過信せず、最終的な品質責任は人間が持つ必要があります。
⚠️ AIの制限事項を理解する
- 複雑なビジネスロジックや暗黙の仕様は理解できない場合がある
- 最新のPlaywrightのAPIやサードパーティライブラリの知識は学習データに含まれていない可能性がある
- プロジェクト固有の設定やコーディング規約は人間が調整する必要がある
🔍 人間が必ずチェックすべきポイント
AIが生成したコードをレビューする際は、以下の観点を重点的に確認しましょう。
- ビジネスロジックの正確性: AIが理解していない、業務固有の重要なルール(例: 特定の条件下でのみ割引が適用される)が正しく反映されているか。
- パフォーマンス: 不要な待機処理(
waitForTimeout
など)や、非効率なループが含まれていないか。 - 保守性: プロジェクトのコーディング規約に準拠しているか。変数名やテストの説明が分かりやすいか。
- セキュリティ: テストデータに個人情報や機密情報が含まれていないか。認証情報がハードコーディングされていないか。
- 環境依存性: ローカル環境とCI環境での動作差異を考慮しているか。
品質管理のチェックリスト
// ✅ 良いAI生成テストの例 test('ユーザー登録機能', async ({ page }) => { // セマンティックロケーター使用 await page.getByPlaceholder('メールアドレス').fill('user@example.com'); // 適切な待機戦略 await page.getByRole('button', { name: '登録' }).click(); await page.waitForResponse('**/api/users'); // 明確なアサーション await expect(page.getByText('登録が完了しました')).toBeVisible(); });
実践検証を踏まえたまとめ
✅ 有効性が実証されたポイント
- 構造化されたプロンプトテンプレートの使用
- セマンティックロケーターの優先(getByRole, getByTestId)
- 段階的な待機戦略(アニメーション、API、DOM更新)
- フォールバック戦略による安定性向上
- エラー情報の詳細な提供
⚠️ 人間による調整が必要な領域
- APIモックと非同期処理のタイミング調整
- 複雑なフォームバリデーションとエラーハンドリング
- 環境固有の動作差異(ブラウザ、CI/CDとの違い)
- ビジネスロジック固有の複雑な条件分岐
🎯 成功のための実践ポイント
- 段階的な実装: 基本的なテストから始めて、徐々に複雑なケースを追加
- フォールバック戦略:
.or()
を活用した安定性の高いロケーター設計 - デバッグファースト: 問題発生時の診断機能を最初から組み込む
- 継続的な改善: AIの出力パターンを学習し、プロンプト品質を向上
結論: AIは開発効率を大幅に向上させる強力なツールです。しかし、生成後の検証・調整プロセスを前提とした開発フローの構築が成功の鍵となります。AIを「副操縦士」として活用し、人間のエンジニアが最終的な品質責任を持つことで、高品質で保守性の高いE2Eテストを効率的に構築できます。