「昨日までグリーンだったテストが、今日は真っ赤に染まっている」。
CIの結果を見て、朝一番に溜息をつくあの瞬間。あの絶望的な気分を味わったことがあるなら、君も俺と同じ「不安定なテストの呪縛」に囚われているはずだ。
「テストが落ちた」んじゃない。「テストの書き方が未熟だった」んだ。かつての俺がそうだったように、多くのエンジニアがE2Eテストを「手動操作の自動化」だと勘違いしている。だが、Playwrightはそんな貧弱なツールじゃない。
今日は、俺が血の滲むような試行錯誤の末にたどり着いた、「絶対に壊れないE2Eテスト」と「CIを爆速で回すためのセキュリティ統合」の極意を叩き込む。
1. 「待つ」という概念を捨てろ。Playwrightに全てを委ねる
テストが不安定になる最大の元凶は `sleep` だ。断言する。コードの中に `sleep` があるなら、それはテストではなく「祈り」だ。
// ❌ 絶対にやるな。これはテストではない、ただの運ゲーだ
await page.waitForTimeout(5000);
await page.click('#submit');
Playwrightには、要素の状態を監視し、準備が整うまで勝手にリトライしてくれるAuto-waitingという神機能がある。これを信じずに自分で待機時間を書くのは、高機能なスポーツカーのアクセルを足で押し戻しているようなものだ。
#### Web-First Assertionsで「状態」を待て
どうしても通信待ちが必要な時も、`sleep` を使ってはいけない。Playwrightの `expect` は、DOMが期待する状態になるまで自動的にリトライを繰り返す。
// ✅ Web-First Assertions を使え
// ボタンがクリック可能になり、かつメッセージが出るまで自動で待機する
const submitBtn = page.locator('button#submit');
await expect(submitBtn).toBeEnabled();
await submitBtn.click();
const message = page.locator('.success-msg');
await expect(message).toHaveText('送信完了', { timeout: 10000 });
この `timeout` の設定も甘く見るな。ローカルの爆速環境で通っても、CI上の非力なコンテナでは5秒以内に終わらないことはザラにある。CI環境では余裕を持たせるのがプロの常識だ。
2. セキュリティスキャンを「テストの一部」に組み込む
E2Eテストが安定したら、次は「脆弱性」だ。リリース後に「SQLインジェクションが見つかりました」なんて絶望的な通知を受け取りたくないなら、CIのパイプラインにセキュリティスキャンをぶち込め。
おすすめは、`docker-compose` を活用した動的スキャンだ。E2Eテストが走る前の「ステージング環境」で脆弱性チェックを走らせるのが最も効率的だ。
# .github/workflows/ci.yml の抜粋
jobs:
security-scan:
runs-on: ubuntu-latest
services:
app:
image: my-app:latest
ports:
- 3000:3000
steps:
- name: Run OWASP ZAP Scan
run: |
docker run -v $(pwd):/zap/wrk/:rw -t owasp/zap2docker-stable zap-baseline.py \
-t http://localhost:3000 -r report.html
ポイントは、「テストが通らなければデプロイさせない」という強制力を持たせること。`npm audit` で依存関係の穴を塞ぎ、ZAPでWebアプリの脆弱性を叩く。これを自動化するだけで、君のプロダクトの信頼性は劇的に向上する。
3. 「やりすぎ」はCIの敵。テスト戦略の再構築
かつての俺は「全画面、全ボタン、全エラーケース」をE2Eでカバーしようとして、CIが30分かかる地獄を作った。結果、誰もブランチをマージしなくなった。本末転倒だ。
E2Eテストは「クリティカルパス」に絞れ。
| テストの種類 | 対象範囲 | 目的 |
|---|---|---|
| ユニットテスト | ロジック、関数単体 | バグの早期発見・網羅性 |
| E2Eテスト | ログイン、決済、購入 | ユーザー体験の破壊を防ぐ |
| セキュリティスキャン | 依存関係、Web脆弱性 | リスクの最小化 |
#### CI爆速化のための戦略:パイプライン分割
1. Smoke Test: 重要な機能だけを抜き出し、PR作成時に即座に実行(5分以内)。
2. Full E2E: 全てのテストを夜間、またはマージ直前に並列実行。
3. Security Scan: 依存関係のチェックは毎朝実行し、脆弱性があれば即座にアラート。
最後に:エンジニアは「いかにサボるか」を考えるべきだ
「テストを書くのが面倒」?
いや、「壊れたテストを直すために休日を潰す方が100倍面倒」だ。
PlaywrightのAuto-waitingに任せ、セキュリティをCIに投げ込み、テスト範囲を賢く絞る。これだけで、君のコードは「誰が触っても壊れない」堅牢なものに変わる。
自動化とは、単に機械に作業させることじゃない。「失敗から解放され、心置きなくコードを書くための権利」を勝ち取ることだ。
さあ、今すぐ `sleep` を消して、俺たちと一緒に「寝ている間にテストが完了している」最高の開発体験を手に入れようぜ。