自動テストビルダー
目標:プロダクトが壊れているときだけ失敗し、一目で理由がわかるテスト。
コードを書く前に
- 既存のセットアップを見つける:
playwright.config.*、pytest.ini/pyproject.toml、フィクスチャ、ヘルパー、ページオブジェクト、テストデータ。それを拡張する。2つ目のフレームワークを追加しない。 - 元になるケースを選ぶ。ない場合は、まずケース(手順と期待結果)をテストの説明に書き、その後コードを書く。
- レイヤーを決める。バグを確実に捉えられる最も安価なレイヤーを使う:
| 証明したいこと | レイヤー |
|---|---|
| ビジネスルール、バリデーション、権限 | APIテスト |
| ユーザーが実際のUIでフローを完了できること | フローごとに1つのE2Eテスト |
| 1つのコンポーネントの多くの状態でのレンダリング | コンポーネントテスト(プロジェクトにあれば) |
| データが実際に変わったこと | UIステップ後のAPIまたはDBチェック |
プロジェクトにまだフレームワークがない場合、Web/APIにはPlaywright Test、Pythonサービスにはpytest + requests から始める。最初のコミットは小さく保つ:設定、1つのフィクスチャ、1つの合格テスト、1つのCIジョブ。
ロケーター
以下の優先順位で使用する:
getByRole(role, { name })– アクセシビリティチェックも兼ねる。getByLabel、getByPlaceholder、getByText– 静的なテキスト用。getByTestId– マークアップがセマンティックでない場合。CSSパスを使うより、開発者にdata-testidを追加してもらう。
インデックス指定のXPath、自動生成クラス名、nth() は、コメントで理由を説明せずに使用してはならない。
待機
waitForTimeoutやsleepを使ってはならない。状態を待つ:await expect(locator).toBeVisible()、page.waitForResponse(url)、またはAPIへのポーリング(expect.poll)。- Playwrightのアサーションはリトライする。テキストを読み取って比較する代わりに
expect(locator)を使う。 - メールやキューなど設計上遅いものは、タイムアウトと明確なメッセージ付きでポーリングする。
テストデータと状態
- テストが必要とするものはAPI経由でフィクスチャ内に作成し、テスト後にクリーンアップする。
- 実行ごとに一意なデータ:タイムスタンプまたは
test.info().workerIndexでサフィックスを付ける。 - ログインはロールごとに
storageStateで1回行い、すべてのテストでUIを通してログインしない。 - テスト間の順序に依存してはならない。すべてのテストが
--grepで単独でパスする必要がある。
構造
tests/
api/ ルールと権限の高速チェック
e2e/ ユーザーフロー、少数で重要
fixtures/ 認証、データビルダー、APIクライアント
pages/ 3つ以上のテストで使用される場合のみページオブジェクト
テスト名は振る舞いで付ける:test_delete_3 ではなく viewer cannot delete a project。テストごとに1つの振る舞い。1つの振る舞いを記述する限り、複数の expect 行は問題ない。
examples/ に例あり:APIセットアップ付きUIフロー、API権限テスト、pytest版。
サードパーティと副作用
その統合がテスト対象でない限り、page.route またはテストダブルで決済プロバイダー、メール、分析、マップをスタブする。実際の統合テストにはタグ(@integration)を付け、CIで個別に実行できるようにする。
テストのフレーク解消
- 再現する:
npx playwright test <file> --repeat-each=20 --workers=4。 - 失敗した実行のトレース(
--trace on)を開き、パスした実行と異なる最初のステップを見つける。 - 一般的な原因:固定待機、2つの要素に一致するロケーター、ワーカー間で共有されるデータ、アニメーション、アサーション後に終了するリクエスト。
- 原因を修正する。CIでのリトライは安全網であり、修正ではない。スキップ理由にチケットリンクがない限り、テストをスキップとしてマークしない。
完了の定義
- テストは単独および全スイートで、3回連続でパスする。
- テストが失敗するのを確認する:アサーションまたはアプリの状態を1回壊し、失敗メッセージが意味をなすことを確認する。
- コードにシークレットがない。認証情報は環境変数から取得する。
- テスト名、ケースID(アノテーションまたはタグ内)、期待結果がレポートで読み取れる。
報告内容:変更したファイル、実行方法、テストのカバレッジ、自動化できなかったこととその理由。