SeleniumからPlaywrightへ:泥沼のE2Eテストを「資産」に変えるための生存戦略
「またテストが落ちてるぞ」。Slackに流れるこの通知を見て、胃が痛くなった経験はないか?
かつて俺も、Seleniumを握りしめて深夜まで「`time.sleep(5)`」の調整に明け暮れる修行僧だった。だが、ハッキリ言おう。Seleniumの時代は終わった。 あの不安定なDOM操作と非同期の同期ズレに固執するのは、ただの無駄な苦行だ。
今すぐPlaywrightに乗り換えろ。CDP(Chrome DevTools Protocol)を直接叩き、ブラウザと密接に通信することで「要素がクリック可能になるまで自動待機」を実現するこのアーキテクチャこそ、我々が求めていた「安定」の正体だ。
1. ログイン処理を「使い回す」:認証の最適化
テストのたびにログイン画面を叩くのは、時間の浪費だ。`storageState`を使って認証情報を保存し、コンテキストを差し込む。これだけで、各テストケースの実行時間は平均30〜40%短縮される。
// auth.setup.ts
import { test as setup } from '@playwright/test';
setup('authenticate', async ({ page }) => {
await page.goto('/login');
await page.fill('input[name="email"]', process.env.TEST_USER!);
await page.fill('input[name="password"]', process.env.TEST_PASS!);
await page.click('button[type="submit"]');
// CookieとLocalStorageを保存
await page.context().storageState({ path: 'playwright/.auth/user.json' });
});
【注意】
`storageState`を使う際、Cookieの有効期限には注意しろ。セッションが切れた瞬間にテストは死ぬ。また、別ドメインへの遷移が発生する場合、`storageState`のスコープが効かないケースがある。その際は、テストごとにログインをエミュレートするのではなく、API経由でトークンを取得して`page.setExtraHTTPHeaders`で注入する方が、はるかに堅牢だ。
2. 「非同期の壁」を突破する:ネットワーク監視の極意
ReactやVueのSPAで、APIレスポンス前にボタンを押してテストが落ちる。これは「Playwrightが悪い」のではなく「テストの書き方が古い」だけだ。単純なクリックではなく、ネットワークの完了をトリガーにしろ。
# APIレスポンスを起点にした堅牢なテスト例
def test_submit_form(page):
# 送信ボタンを押すと同時にAPIリクエストを監視
with page.expect_response(lambda res: "/api/v1/submit" in res.url and res.status == 200):
page.get_by_role("button", name="送信").click()
# DOMの更新を待つ
expect(page.get_by_text("完了しました")).to_be_visible()
この書き方に変えるだけで、`sleep`による「待ち時間」という名の負債が、劇的に減るはずだ。
3. メンテナンス地獄からの脱出:Locatorsを使い倒せ
「UIが変わるたびにテストが壊れる」という嘆きは、CSSセレクタ(`.btn-primary > div > span`など)に依存している証拠だ。
Playwrightの`Locators`(`getByRole`, `getByLabel`など)を使え。これらは、ユーザーが画面を見るのと同じ「意味的な構造」で要素を特定する。CSSのクラス名が変わっても、テストは壊れない。
- Bad: `page.click('.css-1a2b3c')`
- Good: `page.get_by_role("button", name="ログイン").click()`
4. CI/CDの現実解:Dockerでフォント問題を殲滅する
「ローカルでは通るのにCIで落ちる」。この原因の多くはフォントの描画差分だ。妥協してスクリーンショット比較を捨てる必要はない。公式のDockerイメージを使えば一発だ。
# .github/workflows/playwright.yml
jobs:
test:
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.40.0-jammy
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx playwright test
公式イメージには必要なフォントや依存ライブラリが全て含まれている。`ubuntu-latest`で自力でフォントをインストールするような無駄な設定は捨てろ。「環境の再現性」こそが、CI/CDを緑色に保つための唯一の鍵だ。
結論:E2Eは「防波堤」であれ
最後に一つだけ。E2Eテストを全機能に網羅させるな。そんなことをすれば、メンテナンスコストでチームが破産する。
1. クリティカルパス(課金・登録・認証)だけをE2Eで守る。
2. 細かいロジックはユニットテストに追い出す。
3. UI変更に強いLocator(`getByRole`)を徹底する。
Playwrightは最強の武器だが、使い手の知性が試される道具でもある。泥臭いSeleniumから卒業し、賢いテスト設計にシフトする。その最初の一歩が、お前のプロジェクトを「負債」から「資産」へと変えるはずだ。
さあ、今日からCIの緑色を眺める快感に溺れようぜ。