.github/workflows/ci.yml の抜粋

「昨日までグリーンだったテストが、今日は真っ赤に染まっている」。

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` を消して、俺たちと一緒に「寝ている間にテストが完了している」最高の開発体験を手に入れようぜ。