Playwrightで「テスト自動化」を資産に変える:深夜の呼び出しをゼロにする戦略的実装

Playwrightで「テスト自動化」を資産に変える:深夜の呼び出しをゼロにする戦略的実装

「またかよ」。深夜2時、枕元で鳴り響くSlackの通知音。本番デプロイ直後に飛んでくるアラート。原因は、ローカルでは完璧に動いていたはずのE2Eテストが、CI環境でだけ気まぐれに落ちる「Flakyテスト」だ。

E2Eテストは、やり方を間違えれば開発者の足を引っ張る「負債」になる。だが、Playwrightの設計思想を正しく理解すれば、それは最強の「守護神」に変わる。今日は、設定地獄から抜け出し、現場で叩き上げた「鉄壁のテスト環境」を構築するロードマップを共有する。


1. なぜ「設定地獄」に陥るのか

多くのプロジェクトで見る `playwright.config.ts` は、肥大化しすぎている。数千行の設定を読み解くのは、もはやデバッグではなく考古学だ。

反面教師:設定を詰め込みすぎた例

// こういう「なんでも入り」の設定は、依存関係が複雑になりすぎて誰も触れなくなる
export default defineConfig({
  timeout: 60000,
  expect: { timeout: 10000 },
  use: { 
    actionTimeout: 5000,
    navigationTimeout: 5000,
    // ...無限に続くオプション
  },
  // 結局、何が原因で落ちたのか追跡不能になる
});

結論から言うと、設定はデフォルトに近いほど強い。 Playwrightの標準機能(Auto-waiting)は、下手に設定を弄るよりも遥かに賢い。設定をいじるのは、デフォルト値ではどうしても解決できない「特殊な要件」が出てきた時だけで十分だ。


2. Flakyテストを撲滅する「アサートの哲学」

「要素が見えたらOK」という書き方は、今すぐやめろ。それがFlakyテストの温床だ。

// ❌ 危険:アニメーション完了を待たずに判定される可能性がある
await expect(page.locator('.modal')).toBeVisible();

// ⭕ 推奨:データが反映されるまで待つ
await expect(page.locator('.user-name')).toHaveText('Taro Yamada');

なぜ `toHaveText` が強いのか? Playwrightは内部的に `MutationObserver` を使い、DOMの変更を監視している。`toBeVisible` は単なる「表示状態」の確認だが、`toHaveText` は「期待するデータがDOMに注入されるまで」を待機する。これこそが、非同期処理の多いモダンなSPAにおいて、テストを安定させる唯一の解だ。


3. CIの爆速化:シャardingの魔力

テストが増えるたびにCIが遅くなるのは、並列化の怠慢だ。GitHub Actionsの `sharding` を使えば、テストを物理的に分割できる。

# .github/workflows/e2e.yml
jobs:
  playwright:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        shard: [1, 2, 3, 4]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm' # node_modulesのキャッシュはここで十分

      - name: Install dependencies
        run: npm ci && npx playwright install --with-deps

      - name: Run Tests
        run: npx playwright test --shard=${{ matrix.shard }}/4

注意:並列化の落とし穴

シャardingを導入する際、「テスト間の依存関係」には細心の注意が必要だ。
  • IDの重複: 同じユーザーデータでテストを走らせると、DB競合で必ず落ちる。
  • 解決策: テストごとにユニークな名前のユーザーを生成するか、テスト終了後にクリーンアップする設計を徹底すること。

4. キャッシュ戦略の「嘘」を見抜く

巷では「`playwright-browsers` をキャッシュしろ」という声が多いが、これには注意が必要だ。キャッシュの復元に時間がかかりすぎて、結局 `npx playwright install` を実行するのと大差ない時間がかかるケースが多々ある。

  • `node_modules`: `setup-node` のキャッシュ機能で十分。
  • `playwright-browsers`: CIのネットワークが安定しているなら、無理にキャッシュせず毎回クリーンインストールする方が、環境起因の「謎のバグ」を排除できる。
「環境を汚さない」ことこそが、最もコストの低い最適化だ。

5. 最後に:テストは「コードベースの鏡」

テストコードが読みづらい、あるいはメンテナンスが困難なら、それはプロダクトコードの設計が悪いというサインだ。

最近のトレンドである Page Object Model (POM) も、やりすぎればただの抽象化の迷宮になる。まずは、テストコードを「ユーザーのストーリー」として記述し、共通処理だけを関数に切り出す。それだけでいい。

改善項目目的
シャarding導入実行時間の短縮(物理的な解決)
アサートの厳格化Flakyの撲滅(論理的な解決)
デフォルト設定の維持保守コストの最小化(運用的な解決)

テストコードは、書いたその日から負債になるか、資産になるかの分かれ道に立っている。深夜に起こされたくなければ、まずは「不安定なテスト」の放置をやめることから始めようぜ。コードは裏切らない。正しい設計さえしていればな。