playwright-in-sandbox について
ブラウザー検証と決定論的なエンドツーエンドテストのための Playwright スキルです。変更したユーザーフローの対話確認、画面検査、回帰テスト作成を支援します。
主な機能
- 01対話型ブラウザー検証
- 02決定論的な E2E テスト作成
- 03スクリーンショットによる画面確認
- 04セレクターと準備完了条件の指針
- 05E2E データと成果物のルール
活用シーン
- 01ブラウザーで UI 変更を検証
- 02ワークフローの回帰テストを追加
- 03Playwright テストの書き換えや統合
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ customware-ai/ skills --skill playwright-in-sandboxインストール後、Claude Code で/playwright-in-sandboxを入力して読み込まれたか確認します。
詳細
サンドボックス内の Playwright
これは、サンドボックスでのブラウザー検証と、決定論的なエンドツーエンドテストを網羅するための主要な Playwright スキルです。
次の 2 つの明示的なモードで使用します。
- インタラクティブサンドボックスモード:タスクの実装が妥当な状態になった後の、最終的なブラウザー検証に使用します。
- 決定論的 E2E モード:変更したフローを永続的な回帰テストで保護すべき場合に、タスクを完了する前に使用します。
このスキルは、意図的に汎用的なものにしています。次の用途に対応します。
- エージェントが UI を実装した後、ブラウザーでの検証が必要なタスクレベルのスクリーンショットベースの検証
- 下流のアプリケーションリポジトリでの、正式な Playwright E2E テストの作成や書き換え
- タスク完了と見なす前に、最終的なブラウザー検証を行う必要があるタスクフロー
バックエンドのみの作業、ブラウザー自動化を行うほどではない単発のページ操作、またはワークフローの一覧と根本原因を把握する前の広範な障害発生時には、このスキルを使用しないでください。
基本的なワークフロー
- ブラウザーを操作する前に、簡潔な QA の対象一覧を作成します。
- まずモードを決めます:インタラクティブサンドボックスモード、または決定論的 E2E モード。
- 永続セッションでアプリを起動するか、起動済みであることを確認します。
- 変更を実装し、Playwright を最終確認に使う前に、機能を妥当な状態にします。
- 変更したフローをインタラクティブに実行し、DOM の状態だけでなく、証拠としてスクリーンショットを確認します。
- 確認した契約を記録します。
- ルートの準備完了を示すシグナル
- モーダルの開閉を示すシグナル
- アクションが有効になる条件
- 保存完了を示すシグナル
- 長期的に使用できる
data-testidまたはセマンティックセレクター
- フローがバグ修正、ワークフロー、回帰テストが重要なもの、または意味のある変更である場合は、決定論的 E2E テストに移行します。
- インタラクティブな検証でプロダクトの動作が誤っていると分かった場合は、プロダクトコードまたはデータ契約を修正します。テストを弱めて、誤った動作を問題なしに見せてはいけません。
- タスクを完了する前に、変更したフローについて次の両方を確認します。
- インタラクティブな検証に成功している
- 永続的な E2E テストがある、またはインタラクティブな検証のみとする明確な理由がある
共通ルール
これらのルールは、インタラクティブサンドボックスモードと決定論的 E2E モードの両方に適用されます。
- インタラクティブ検証は、変更後の最終確認として行います。実装がまだ半端な状態で、作業途中にランダムに試すものとして扱わないでください。
- ブラウザーで製品の動作に問題があると判明した場合は、機能または基盤となるデータ契約を修正してください。バグを抱えたままテストを通すための小手先の方法を考案しないでください。
- リポジトリの標準 E2E データベース契約を厳守してください。リポジトリ標準が
e2e.dbなら、e2e.dbを使用してください。e2e.dbがなく、リポジトリがその使用を想定している場合は、e2e.dbを作成または用意し、その契約を使い続けてください。通常のアプリケーションデータベースへ黙って切り替えないでください。 - 期待値、ステータス、割り当て、集計値を導き出す際は、標準 E2E データベースまたはシード済みの業務データを優先してください。リポジトリで
better-sqlite3を使用している場合は、UI を検証する前に実際の期待値を確認するため、データベースを直接調べてもかまいません。 - セレクターは次の順に優先してください。
- 明示的な
id、data-*、data-testid、その他の所有されたセマンティック契約 - 安定したアクセシブル名を持つアクセシブルロール
- ラベルとコントロールの関連付け
- 安定した URL、パス名、またはクエリ契約
- テキスト自体が製品の契約である場合に限り、テキストのみのセレクター
- 意図的な構造チェックに限り、CSS、XPath、または DOM 順序に基づくセレクター
- 明示的な
- 最終確認の前に、失敗した実行や置き換えられた実行で生成された古いスクリーンショット、トレース、一時ファイルを削除してください。
- リポジトリに保守されている全スイート実行、夜間 QA 実行、自動ヘルスチェックがある場合は、実際に実行されたか、問題なく完了したかを把握してください。対象を絞ったチェックだけで、恒久的にスイートの健全性確認に代えることはできません。
- 移行されたアプリケーションや単発のクライアントアプリケーションによっては、一般的な新規開発アプリよりも広範な移行検証が一時的に必要な場合があります。それは許容されますが、品質基準は変わりません。決定論的なセレクター、所有されたデータ、実際のユーザー契約を使用し、見せかけの成功を作らないでください。
モードの選択
次の場合はインタラクティブサンドボックスモードを使用します
- 実装がすでに妥当な状態にある
- 変更したフローがユーザーにとって実際に機能することを、ブラウザーで最終確認する必要がある
- UI が実際に正しいか判断するためのスクリーンショットが必要である
- 自動テストを作成または更新する前に、準備完了の条件、モーダルの動作、または安定したセレクターを把握・確認する必要がある
次の場合は決定論的 E2E モードを使用します
- 変更によってバグが修正される
- タスクによってユーザーワークフローが新たに作成される、または大幅に変更される
- フローがビジネス上重要である、またはリグレッションが発生しやすい
- 既存の Playwright カバレッジを書き直す、統合する、または廃止する
- リグレッション防止策なしではタスクを完了とみなすべきでない
次の場合に限り、インタラクティブモードのみを継続します
- 変更が探索的または一時的である
- フローがまだリグレッションテストとして記述できるほど安定していない
- タスクによって保守対象のワークフローが実質的に変わらない
- 移行されたアプリや単発のアプリで一時的な検証が必要だが、永続的な E2E カバレッジへ移行できるほど安定していない
コミットする E2E カバレッジへ移行しない場合は、その理由を明確にしてください。
共有環境の契約
- リポジトリで別の設定が明示されていない限り、
localhostより127.0.0.1を優先してください。 - まず、リポジトリで明示されているサーバーの契約に従ってください。リポジトリに定義がない場合は、サンドボックスの一般的なデフォルトとして
4444を使用してください。 - サンドボックス環境では、Playwright のブラウザーが
/ms-playwrightにある場合があります。デフォルトのキャッシュパスにあると決めつけないでください。 - サンドボックス環境では、Chromium をヘッドレスモードで明示的に起動してください:
chromium.launch({ headless: true })。 - 実行環境のペイロードに不確かな点がある場合は、Playwright のブラウザーパスを確認してください:
echo "$PLAYWRIGHT_BROWSERS_PATH"
ls -al /ms-playwright
page.goto(...)の前に、対象のポートが実際にリッスンしており、アプリが応答することを確認してください。- 標準の実行では、リポジトリで定められた標準の E2E データベース契約を使用してください。リポジトリの標準が
e2e.dbの場合は、必ずe2e.dbを使用してください。 - リポジトリが
e2e.dbを想定していて、存在しない場合は、テストの実行前にe2e.dbを作成またはプロビジョニングしてください。 - 代替の DB 名やパスを使用できるのは、リポジトリが分離された検証レーンを明示的にサポートしており、ワーカーの実行を意図的に分離する場合に限ります。
- 対話型の成果物は、コミットする回帰テスト用のアセットとは分けてください。
- スクラッチスクリプトやスクリーンショットは、一時フォルダーまたは専用の成果物フォルダーに保存してください
- コミットする回帰テストは、
tests/e2e/またはリポジトリで正式に定められたテスト場所に保存してください
- 最終確認の前に、失敗した実行や置き換えられた実行で生成された古いスクリーンショット、トレース、一時成果物を削除してください。
- 複数の書き換えレーンまたは検証レーンを並行して実行する場合は、次の実行時リソースを分離してください:
- ポート
- データベースまたはシード状態
- 出力フォルダー
- スクリーンショットとトレース
対話型サンドボックスモード
変更の実装が検証できる程度まで完了した後、ユーザーフローが現時点で正常に機能することを確認するには、このモードを使用してください。
対話型モードは、一度成功するまで試行錯誤を続けてよいという意味ではありません。変更を実装し、機能が動作するはずだと判断した後に使用し、ブラウザーで実際のユーザーフローを最終的に視覚的・機能的に検証してください。
QA インベントリ
次の 3 つの情報源からインベントリを作成してください:
- ユーザーが求めた要件
- 実装または変更した、ユーザーに見える動作
- 最終回答で述べる予定の内容
これらのいずれかに含まれる項目はすべて、最終確認前に少なくとも 1 つの QA チェックに対応付けてください。
次の項目を列挙してください:
- 最終確認する予定の、ユーザーに見える内容
- 意味のあるコントロール、モード切り替え、実装したインタラクティブな動作のすべて
- 各コントロールが引き起こす状態変更または表示変更
- 少なくとも 2 つの探索的な検証、または通常の操作手順から外れた検証
デスクトップ検証スクリプト
デバッグ対象のアプリに TARGET_URL を設定してください。localhost より 127.0.0.1 を優先してください。
import { chromium } from "playwright";
const TARGET_URL = "http://127.0.0.1:4444";
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
viewport: { width: 1600, height: 900 },
});
const page = await context.newPage();
try {
await page.goto(TARGET_URL, { waitUntil: "domcontentloaded" });
console.log("Loaded:", await page.title());
// Add the task-specific interactions and assertions here.
await page.screenshot({ path: "playwright-desktop.png", type: "png" });
} finally {
await context.close().catch(() => {});
await browser.close().catch(() => {});
}
モバイル検証スクリプト
タスクがレスポンシブレイアウトまたはタッチ操作に影響する場合は、モバイル用のスクリプトを別に使用してください。
import { chromium } from "playwright";
const TARGET_URL = "http://127.0.0.1:4444";
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
viewport: { width: 390, height: 844 },
isMobile: true,
hasTouch: true,
});
const page = await context.newPage();
try {
await page.goto(TARGET_URL, { waitUntil: "domcontentloaded" });
console.log("Loaded mobile:", await page.title());
// Add the task-specific interactions and assertions here.
await page.screenshot({ path: "playwright-mobile.png", type: "png" });
} finally {
await context.close().catch(() => {});
await browser.close().catch(() => {});
}
反復モデル
- 目的を絞った各フローに対して、独立した Node.js 検証スクリプトを 1 つ使用してください。
- コードを変更した後は、実行間で状態を維持しようとせず、新しいプロセスから検証スクリプトを再実行してください。
- 各スクリプトの範囲を絞り、変更したフロー 1 つ、その主なアサーション、スクリーンショットの成果物だけを含めてください。
- デスクトップとモバイルの両方が重要な場合は、別のスクリプトまたは別々の実行を使用してください。
- スクリーンショットの確認は、この契約の一部です。DOM のアサーションだけで最終確認を済ませないでください。
対話型チェックリスト
セッションの流れ
- QA インベントリを作成する
- コードを変更する
- 現在のフローに対する最終的なブラウザー検証として、Playwright 検証スクリプトを実行する
- 実際のユーザー入力を使って機能 QA を再実行する
- 視覚的な QA を別途再実行する
- 実際に評価する UI の状態にしてから、最終的な成果物を取得する
- 正式な E2E で信頼できるセレクターと準備完了の判定条件を記録する
機能 QA
- サインオフには実際のユーザー操作を使用します。キーボード、マウス、クリック、タッチ、または同等の Playwright 入力 API を使用してください。
- エンドツーエンドの重要なフローを少なくとも 1 つ検証します。
- フローの内部状態だけでなく、画面上に表示される結果を確認します。
- その場限りの抜き取り確認ではなく、共有 QA インベントリに沿って進めます。
- サインオフ前に、ハッピーパスだけでなく、明らかに操作可能なコントロールをすべて少なくとも 1 回確認します。
- スクリプトによるチェックに合格したら、通常の入力を使って短い探索的テストを行います。
page.evaluate(...)は状態の確認や準備に使用できますが、サインオフ用の入力とはみなされません。
ビジュアル QA
- ビジュアル QA は機能 QA とは別に実施します。
- 画面上の各要件を、該当する状態で明示的に確認します。
- スクロールする前に、最初のビューポートを確認します。
- QA 中に到達できる、最も情報量の多い現実的な状態を確認します。
- クリッピング、オーバーフロー、歪み、コントラスト不足、レイヤーの崩れ、不自然な動き、古いオーバーレイがないか確認します。
- 見落としていた非表示のブロッカーがあったために UI が「動作する」だけなら、そのフローはサインオフできる状態ではありません。
インタラクティブなサインオフ
- 通常のユーザー入力で機能フローに合格している
- ビジュアルチェックで関連するインターフェース全体を確認している
- 想定される初期表示について、ビューポートへの収まりを確認している
- 最終スクリーンショットが、サインオフ対象の要件と一致している
- 探索的テストを最終回答で明記している
- E2E 作成に使う、安定したセレクターと準備完了の判定条件を記録している
- 失敗した試行で生成された古いスクリーンショットや一時的な成果物を削除している
決定論的 E2E モード
実際の Playwright 回帰テストを作成または書き直す場合は、このモードを使用します。
目的は、実際の機能を保護することです。アプリの動作が誤っている場合は、アプリを修正してください。テストを調整してバグを残してはいけません。
ワークフロー
- インタラクティブな検証ですでに確認できた内容から始めます。
- 確認できた UI の契約を、安定した自動チェックに落とし込みます。
- 各仕様は、1 つのワークフロー群または一貫性のあるユーザージャーニーに絞ります。
- 各テストがセットアップを所有するか、明示的に受け取るようにします。
- テストが管理していないマジックリテラルではなく、正規のシードデータやデータベースに基づく期待値を、値、ステータス、集計に優先して使用します。
- レガシーのテストを削除または統合する前に、変更したフローを検証します。
- 脆弱なテストスイートを書き直す場合は、削除した各シナリオを以下のいずれかに割り当てます。
- 維持
- 理由を明示して統合
- 根拠を示して意図的に廃止
- 明確な説明を付けて隔離
セレクターの優先順位
より適切な契約がある場合、たまたま存在するテキスト、汎用的なコンボボックスのパターン、視覚的なスタイル、不安定でオーバーレイの影響を受けやすい DOM 構造に依存する、永続的なテストを作成してはいけません。 テキスト自体が製品の真の契約である場合を除き、テキストのみのセレクターは最後の手段です。
待機と準備完了のルール
waitForLoadState("networkidle")をデフォルトで使用してはいけません。- ナビゲーションでは、URL の変更とページ準備完了のセンチネル、またはレスポンスの契約と準備完了のセンチネルを待ちます。
- ダイアログでは、操作前に明示的な開いた状態を待ち、次の依存するステップの前に閉じた状態を待ちます。
- 保存では、観測可能な保存完了の契約を待ちます。
- 非同期コントロールでは、クリックする前に、コントロールが有効になる条件をアサートします。
- オーバーレイ、ドロワー、コマンドパレットを伴うフローでは、次の画面を操作する前に、それらが閉じていることを確認します。
- 別の画面要素が引き続きフォーカスまたはポインターイベントを捕捉しているために操作が失敗する場合は、リトライを重ね続けるのではなく、準備完了の判定モデルを修正します。
ナビゲーションとアサーションのルール
- 実装ではなく、動作を検証します。
- 内部実装の詳細より、ユーザーに見える結果を優先します。
- 数値、ステータス、担当者の割り当て、集計値がシード済みの業務データに由来する場合は、まずテスト側で設定した内容または正規の DB 契約から期待値を導き、その後、UI がその値と一致することを検証します。
- テキスト自体が契約である場合に限り、テキストアサーションを使用します。
- 実際の契約が特定のカード、セクション、ダイアログ、行にある場合は、ページ全体を対象にした広範なテキスト照合を避けます。
- 仕様を十分に見せるためだけに、同じワークフローの結果に対する冗長なアサーションを複数残さないでください。
- セレクターの範囲を広げたり、期待値を弱めたり、現在のバグを受け入れたりして、失敗するテストを成功扱いにしないでください。ただし、その弱い契約が実際に意図された製品の動作である場合は除きます。
厳禁事項
- 主な準備完了判定として
networkidleをデフォルトで使用すること - UI から直接検証できる動作のアサーションに
page.evaluate(...)を使用すること - 複数のワークフローにまたがる巨大な包括的仕様
- 主たる契約として
button[role="combobox"]のような汎用セレクターを使用すること - 前のテストで残った状態を暗黙に再利用すること
- ワークフローの対応関係を明確にする前に、レガシーテストを削除または統合すること
失敗収束プロトコル
多くのテストが失敗した場合、デフォルトで一つずつ修正しないでください。
- まず、失敗を根本原因ごとに分類します。
- 認証またはブートストラップ
- 古いサーバーまたは共有ポートの競合
- モーダルまたはオーバーレイの状態
- セレクター契約の不足
- 準備完了判定の不足
- データまたはセットアップの非決定性
- 古くなったワークフローの前提
- 個別のテストを修正する前に、共通の契約を修正します。
- 仕様の構成が不適切な場合は、修正を中断し、そのワークフローファミリーを書き直します。
- 複数のワークフローを混在させているために仕様が繰り返し壊れる場合は、包括的な仕様を廃止して分割します。
書き換えのガバナンス
- カバレッジの減少は、意図せず発生させず、明示します。
- 削除したレガシーアサーションにはすべて、対応する置き換え、または廃止の根拠を記述します。
- 重複した成功確認より、意味のある統合を優先します。ただし、ユーザージャーニーのカバレッジを黙って減らさないでください。
fixmeのカバレッジを隔離したままにするのは、次の条件を満たす場合に限ります。- 動作が実際に阻害されている
- 隔離が明示されている
- ファミリーの残りの部分を引き続き安全に進められる
- 正式な E2E アセットはコミット対象のテストディレクトリに置き、探索用のスクリプトやスクリーンショットはそれらのディレクトリに置かないでください。
並行書き換えの検証
並行した書き換えは可能ですが、担当範囲と実行時の分離が確保されている場合に限ります。
- ワークフローファミリーごと、または重複しないファイルの担当範囲ごとに並行作業します。
- 明示的な担当者を決めずに、複数の作業者が同じ包括的な仕様や共有ヘルパーを編集しないでください。
- 作業者が並行して検証する場合は、次を分離します。
- ポート
- データベースまたはシードパス
- 出力フォルダー
- スクリーンショット、トレース、アーティファクト
- 実行時の分離ができない場合は、書き換えのコーディングを並行して進めても、Playwright の検証は順番に実行します。
フルスイートの鮮度
- 対象を絞った検証は高速に保ちつつ、維持対象のフルスイート契約が劣化しないようにします。
- リポジトリまたは自動化スタックが毎日、夜間、またはリリース前のフルスイート実行に対応している場合は、品質を可視化する仕組みの一部として扱います。
- 自動エージェントに QA を成功状態に保つことを期待する場合は、実行したこと、実行内容、成功状態を維持できたかを確認できる証拠が必要です。
- 対象を絞った仕様が成功しても、より広範なスイートを長期にわたって維持することの代わりにはなりません。
開発サーバー
ローカルで Web をデバッグする場合は、アプリを永続的な TTY セッションで実行し続けてください。短命なシェルから一度だけ実行するバックグラウンドコマンドに頼らないでください。
まず、リポジトリに記載された起動手順を使用します。明示的な規約がない場合は、一般的なサンドボックスのパターンとして次を使用します。
pnpm run build
PORT=4444 pnpm run start
page.goto(...) の前に、対象ポートでリッスンしていることと、アプリが応答することを確認します。
対話的な検証が完了したら、起動したサーバープロセスを停止し、サンドボックスを以降のタスクに備えてクリーンな状態に保ちます。
よくある失敗パターン
- オーバーレイやモーダルのブロッカーが実際には閉じられていないのに、ブラウザのフローが成功してしまいます。
- DOM が変更されたことはテストで証明できても、ユーザーに見えるフローが機能することは証明できていません。
- スペックで誤った名簿、シードデータ、または ID の前提を使い、偽の状態を「テスト」してしまいます。
- アプリやデータの契約を修正せず、現在のバグに合わせてテストを書き換えることで、テストを成功させてしまいます。
- テストが、テストで管理する DB やシード状態から導出すべき表示テキスト、件数、または値をハードコードしています。
- ワーカーがファイルを並行して書き換えても、検証では依然として単一の固定ポートと単一の変更可能なデータベースを共有しています。
- テストを適切に統合せず、重複テストを残したために、テストスイートが成功しているように見えます。
- 抽出した各スペックがどのワークフローを担当するのか、誰も整理していないため、大規模な一括スペックが固有のカバレッジを覆い隠し続けています。
サインオフの要件
- 変更したフローについて、対話的な検証が行われていること。
- 回帰に関わるフローには、永続的な E2E カバレッジもあること。
- ブラウザーの証跡が、最終回答で述べる内容と一致していること。
- セレクター、待機処理、アサーションが、実際の UI の契約に基づいていること。
- スキップ、隔離、統合、または廃止したカバレッジを明示していること。