これは今の時点での“僕なりのやり方”
まずはじめに断っておくと、ここに書いているのは「今の自分が、現場でやってみてこういう方向にしたらうまくいきそう」と思ったものであって、いつか見直すかもしれないし、誰にでも当てはまる正解ではないです。
なので「ふーんこういう感じでやると進めやすそうなんだな」くらいに思ってもらえればうれしいです。
はじめに
5年以上開発が続くレガシーな業務アプリケーションに、E2Eテスト(End-to-End Test)をPlaywrightで導入し始めた。本記事では、その方針や考え方、試行錯誤、得られた知見を整理する。
単なる作業ログではなく、「どういうトレードオフがあって、なぜそう判断したのか」を残すことで、今後の意思決定や他プロジェクトへの展開時にも役立てたい。
背景
- 単体テスト(Vitest等)はすでに一定存在
- ただし、E2Eが存在しないことで「何かが壊れていた」に毎回時間を消耗
- ページ単位・機能単位での「最低限の動作保証」が必要
- CI実行コストも考慮し、まずはローカル中心で導入開始
当初は「Vitestだけで十分では?」と考えていた。コンポーネント単位でのテストは状態の切り分けや意図的な制御が容易だからだ。
しかし実際のレガシーコードでは、状態やデータ構造が複雑すぎて「どんなpropsを渡せばよいかすら不明」という場面が多発した。
Next.jsのようにサーバーサイドロジックやハイドレーション後の状態が絡むケースもあり、ユニットテストだけでは網羅が難しい。
そのため、PlaywrightでUIを通じて仕様を確認・動作確認するというアプローチの方が現実的と判断した。
方針の基本設計とトレードオフ
一気に完璧な体制を目指すのではなく、段階的に進められるよう「壊さないこと」「壊れたらすぐ気づけること」を優先。
そこで、CORS回避やUIのデバッグ速度などを考慮し、初期段階ではChromium限定で構築している。他ブラウザ対応やCI統合は後回し。
選択の理由
- 実行の速さと安定性を優先(ローカル中心)
- UIの構造理解より「ユーザーとして動くか」に注目
- レガシーの内部構造を把握するより、まずは既存の動作を守る
ステップ別戦略
Step 1: 実環境ベースでの導入
トレードオフ: モックより手軽だが、データ依存やCORS制約あり
playwright-msw
による完全モックはまだ導入しない- 開発用実環境のAPIを活用して、ログインや画面操作を検証
APIRequestContext
を使って事前に認証状態を生成
test.use({
bypassCSP: true,
launchOptions: { args: ['--disable-web-security'] },
video: 'on',
screenshot: 'only-on-failure',
})
Step 2: スモークテストを先行
トレードオフ: 完全網羅より、「最低限の動作確認」を優先
- ログインや検索など、致命的な画面だけ確認する
- 「開いてエラーが出ない」だけでも価値がある
- 今後増やすことを前提に、最短ルートのシナリオをベースに設計
Step 3: シナリオベースに設計
トレードオフ: UI単位よりも、ユーザー体験単位で整備
- 「検索 → 詳細閲覧 → 操作完了」までを1シナリオに
- コンポーネントの粒度よりも実際の操作感を重視
- シナリオが長くなれば適宜分解する
モック戦略とデータの扱い
- 実環境で理解を深めながら、モックへの移行を視野に
- モック導入時は、fixtureなどで状態を明確化
- IDベタ書きを避け、抽象化されたデータを使う
CORS回避策
- Chromium限定で
--disable-web-security
を使用 - 認証などは
APIRequestContext
を使って直接処理
CIは後回しに
トレードオフ: 安定しないテストをCIに載せても開発効率を下げるだけ
- 最初はローカル実行のみに絞る
- 「文化と書き方」が安定したらGitHub Actions等に統合
- 安定するまでは人の目で確認でもよいと割り切る
Feature Flagとの付き合い方
トレードオフ: 条件分岐が多すぎるとテストが壊れやすくなる
- Dev環境で有効な状態を前提にテストを書く
process.env
経由でテスト用ユーザーを切り替え、最小限のフラグ分岐で済ませる
守るべきポイントの優先順位
- クリティカルな機能から手を付ける
- 例:ログイン、検索、主要ページ遷移
- ソートやフィルターは後回しでも支障は少ない
- 守るべき機能はPO・QAとすり合わせて決める
ゴールと期待する効果
- 安心して変更できる土台を作る
- PO・QAが「これが通れば安心」と思える状態を整備
- テストを通じて、仕様・依存・操作の構造化が進む
期待される具体的なメリット
- リファクタ時の安心感と判断基準が生まれる
- 手動テストの省力化・受け入れ速度の向上
- ドキュメント化されていない仕様も、テストで見えるようになる
- UIデバッグの時間削減(動画やスクリーンショット付き)
最後に:完璧じゃなくてもいい
「全部テストしよう」と思うとしんどくなる。
最初は「壊れたら困るところ」だけでいい。
小さく始めて、動いていることを積み重ねていこう。
Playwrightは楽しい。スクショも動画も撮れる。失敗すれば即わかる。
レガシーコードにこそ、E2Eテストは意味がある。