「テストコードなんて書いてる暇があったら機能実装しろよ」――。
半年前の俺は、本気でそう思ってた。それが、ある金曜日の夜。リリースボタンをポチった瞬間に本番環境のログイン機能が全滅した時、血の気が引く感覚を味わうことになるとは夢にも思わなかったんだ。
ユーザーからの「ログインできないんだけど?」という通知がDiscordに雪崩れ込んできて、結局オールで切り戻し作業。あの時の絶望感といったら、もうトラウマレベルだ。あの夜、俺が手動デプロイという名のロシアンルーレットを卒業し、Playwrightという「盾」を導入すると誓ったのは言うまでもない。
1. 【黒歴史】セレクタ地獄で自爆した話と、唯一の脱出ルート
テストを書くのが億劫なのは、みんな「完璧なテスト」を目指しすぎるからだ。最初からカバレッジ100%なんて目指すな。まずは「ログインしてマイページが見れるか」だけ自動化する。これだけでリリース時の心拍数は劇的に下がる。
Playwrightが最高なのは `codegen` という魔法があるからだ。
npx playwright codegen http://localhost:3000
これを叩いてUIをポチポチするだけでコードが生成されるが、ここで注意が必要だ。 俺は最初、生成されたコードをそのまま使って大火傷をした。CSSセレクタで `div > div > span:nth-child(2)` みたいに構造をベタ書きしてたんだ。
デザイン調整で `div` が一つ増えただけで、全テストが真っ赤に染まる。「テストが壊れるからUI変更できない」という本末転倒な状況だ。
教訓:`data-testid` を信じろ。
HTMLに `data-testid="login-button"` を埋め込むんだ。これならデザインが変わろうがテストは死なない。
#### 良いテストコードの書き方(リファクタリングの視点)
`codegen` で出たコードはあくまで「下書き」。これを保守性の高い形に昇華させる。
// 修正前:CSSセレクタ依存(脆い)
await page.click('div > div > button');
// 修正後:data-testidで特定(堅牢)
await page.getByTestId('login-button').click();
2. あの夜の悪夢を二度と繰り返さないために
手元でテストが通るのは当たり前。GitHub Actionsで、プルリクを投げた瞬間にテストが走る環境を作らなきゃ意味がない。あの夜、手動デプロイの怖さを骨の髄まで知った俺は、このYAMLを書いてマージの安全を担保した。
name: Playwright Tests
on: pull_request
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm install
- run: npx playwright install --with-deps
- run: npx playwright test
これで、テストが落ちればマージボタンが押せなくなる。この「強制力」こそが、俺たちエンジニアを守る最強の防壁なんだ。
3. 【並列実行の罠】ローカルでは通るのにCIで死ぬ理由
テストが増えてくると、実行時間が気になり始める。Playwrightはデフォルトで並列実行してくれるんだけど、これがまた曲者だ。
やってはいけない例:
// テストAでユーザー作成、テストBで削除
test('ユーザー作成', async () => { await createUser(); });
test('ユーザー削除', async () => { await deleteUser(); });
これ、並列で走るとAが作る前にBが削除しにいったり、Aが作成したユーザーをBが横取りしてエラーになる。ローカルのシングルスレッド実行だと再現しないから、CIで落ちてから気づくという地獄を見る。
修正後のコード:
各テストで独立した環境を作るのが鉄則だ。
// 各テストでユニークなユーザーを生成し、終了後にクリーンアップする
test.afterEach(async ({ page }) => {
await page.evaluate(() => localStorage.clear());
// 必要ならここでDBのクリーンアップ処理も呼ぶ
});
最後に:テストは「サボるための投資」だ
テスト自動化は「保険」じゃない。「開発のスピードを上げるためのエンジン」だ。テストがあるからこそ、金曜の夜に安心してデプロイできるし、大胆なリファクタリングも怖くない。
まずはログイン画面のテストを1つ書くところから始めろ。次にやるべきは「決済フロー」や「フォーム送信」といった、落ちると致命的なクリティカルパスの自動化だ。
最初は面倒かもしれない。でも、あの冷や汗を二度と味わいたくないなら、今すぐ `npm init playwright@latest` を叩け。
テストは書くものじゃない。自分を守るための盾を作る作業だ。その盾があれば、俺たちはもっと自由に、もっと速くコードを書けるようになるんだから。