結論から書きます。E2Eで守るべきものは、その結果次第で「出す/止める」の判断が変わる境界だけです。 ユーザー体験のすべてではありません。
E2Eテストを書き始めると、ほぼ必ずこの壁にぶつかります。「どこまでE2Eで守るべきなのか」「何をテスト対象に含め、何を切り捨てるのか」。
PlaywrightやCypressのような強力なツールが普及したことで、「技術的に書ける範囲」と「守るべき範囲」が混同されやすくなったと私は感じています。
この記事では、E2Eテストにおいて何を守るかをどう決めるのか、そしてPlaywright / Cypress を前提に、どう品質を作ると実務で機能するのかを書きます。
対象読者は、次のような実務レベルのエンジニアです。
- E2EテストをすでにCIで回している
- テストはあるが、リリース判断が楽になっていない
- 「増やす/減らす」の判断に毎回悩んでいる
スポンサーリンク
前提:E2Eは「ユーザー価値の破壊」を検知する仕組み
まず、判断軸を明示します。E2Eテストが守る対象は、ユーザーが価値を受け取るまでの“連続した体験”が壊れていないことです。
これはツールや流派の話ではありません。テストレイヤーごとの役割分担を整理すると、必ずここに収束します。
| 問い | 担当するレイヤー |
|---|---|
| 個々の関数が正しいか | 単体テスト |
| モジュール同士が正しく連携するか | 結合テスト |
| ユーザーが目的を達成できるか | E2Eテスト |
つまりE2Eは、「この操作をしたユーザーは、最後まで目的を達成できるか」を判断するためのテストです。
この前提を外した瞬間、E2Eは簡単に“数だけ多い信用できないテスト”になります。 テストピラミッドの考え方が「上に行くほど本数を絞る」としているのも、E2Eが遅く壊れやすいからというだけでなく、判断に使える粒度が粗いからです。
「重要そうだから守る」は失敗する
E2Eで守るべきものを決めるとき、多くの現場でこんな決め方がされます。
- 売上に関わるから重要
- 主要画面だから重要
- PMが心配しているから重要
この決め方で、E2Eが膨れ上がり、判断に使えなくなる現場を何度も見ました。
理由は単純です。「重要そう」という基準は、壊れたときの判断に使えないからです。
E2Eで本当に必要なのは、重要かどうかではなく次の問いです。
そのフローが壊れたとき、リリース可否の判断は変わるか?
ここに即答できないものは、E2Eで守る価値がありません。
スポンサーリンク
守るべきものは「判断が変わる境界」だけ
E2Eで守るべきものは、その結果次第で「出す/止める」の判断が変わる境界だけです。
| E2Eで守る | E2Eで守らない |
|---|---|
| ログインできるか | 表示の細かな分岐 |
| 購入・申込み・送信まで到達できるか | バリデーション文言の差異 |
| 主要なロールで、致命的な操作が完遂できるか | 一部条件でのみ起きるUI分岐 |
右側のものは重要でないわけではありません。E2Eで判断する対象ではないだけです。文言の差異は単体テストかスナップショットで、UI分岐はコンポーネントテストで守ったほうが、落ちたときに原因がすぐ分かります。
この考え方の土台はE2Eテストの品質基準に書いています。
Playwright / Cypress それぞれの前提の違い
「どちらが優れているか」ではなく、「制約が違うので設計が変わる」という話です。 守る範囲を決めたあと、実装方針はツールの前提に引きずられます。
| 項目 | Playwright | Cypress |
|---|---|---|
| 実行位置 | ブラウザの外(プロセス外から操作) | ブラウザの中で実行 |
| 対応ブラウザ | Chromium / Firefox / WebKit | Chromium系 / Firefox |
| 複数タブ・複数オリジン | そのまま扱える | cy.origin() を使う必要がある |
| 並列実行 | ワーカー数の指定だけで動く | 公式の並列実行は --record + Cypress Cloud が前提 |
| デバッグ | Trace Viewer(実行後に再生) | Test Runner のタイムトラベル(実行中に確認) |
設計に一番効くのは「複数オリジン」と「並列実行」です。
外部の決済画面やSSOを経由するフローを守りたい場合、Playwrightならそのまま1本のテストで書けます。Cypressでは cy.origin() でオリジンをまたぐ記述が必要になり、書き方が変わります。「決済まで通す」を守ると決めたなら、この差はそのまま実装コストになります。
並列実行も同じです。Cypressの公式な並列実行は、Cypress Cloud への記録(--record)が前提です。自前CIだけで分散させたいなら、spec を手動で分割するなどの工夫が要ります。Playwrightはワーカー数を指定するだけなので、「本数を増やしても時間で殴れる」前提が置けます。
スポンサーリンク
Playwright / Cypress 前提での品質設計の原則
「何が壊れたら落ちるか」をテスト名で言語化する
E2Eテストは、コードより先に「日本語で説明できる状態」であるべきです。
- どのユーザーが
- 何をしようとして
- どこで失敗したら落ちるのか
これがテスト名から読み取れないなら、そのテストは判断に使えません。
// 悪い例:何が壊れたら落ちるのか読み取れない
test('購入フロー', async ({ page }) => { /* ... */ });
// 良い例:落ちた瞬間に疑う場所が決まる
test('ログイン済みユーザーがカートから決済完了まで到達できる', async ({ page }) => { /* ... */ });
1テスト = 1判断
PlaywrightでもCypressでも、1テストで複数の判断をさせると、失敗時に必ず迷います。
ログイン → 遷移 → 入力 → 送信 を全部詰め込むのではなく、「どこまで通ればOKなのか」を1つに絞ります。
長いテストより、判断が鋭いテストの方が価値があります。 ログインは前提条件であって判断対象ではないなら、Playwrightの storageState やCypressの cy.session() で毎回の手順から外してしまうほうが、テストの意図が明確になります。
安定性より「説明可能性」を優先する
E2Eは「絶対に落ちない」必要はありません。 落ちたときに次の2つが即座に分かるなら、多少落ちても品質は下がりません。
- 何が壊れたか
- どこから疑えばいいか
むしろ、理由の分からない安定は実務では害になります。 リトライで緑になるテストを放置すると、チームは「落ちても再実行すればいい」と学習します。そうなった時点で、そのテストは判断材料ではなくなります。
Playwrightなら Trace Viewer、Cypressならスクリーンショットと動画をCIの成果物として必ず残す設定にしてください。説明可能性はツール設定で買えます。
「守らないもの」を明確にすると、E2Eは強くなる
E2E設計で一番大事なのは、あえて守らないものを決めることです。
| 対象 | 守る場所 |
|---|---|
| 計算ロジック、条件分岐 | 単体テスト |
| API・DBとの連携 | 結合テスト・APIテスト |
| 見た目の崩れ | ビジュアルリグレッション |
| 文言・体裁 | 人のレビュー |
| 目的の達成可否 | E2E |
この切り分けをしないままE2Eを増やすと、PlaywrightでもCypressでも必ず破綻します。
私はいつも、こう自問します。
この失敗を見て、私は迷わず判断できるか?
迷うなら、そのテストは設計ミスです。
アップロードのように外部サービスをまたぐ処理をどこまでE2Eに含めるかは、S3アップロードのパターン集で具体例を書いています。
まとめ:E2Eの品質は「守った数」では決まらない
- 守るべきものは、判断が変わる“境界”だけ。 ユーザー体験のすべてではない
- 「重要そうだから」は基準にならない。「壊れたらリリース判断が変わるか」で決める
- 文言・UI分岐・見た目はE2E以外のレイヤーに逃がす
- 複数オリジンを跨ぐならPlaywrightが素直。 Cypressは
cy.origin()が要る - Cypressの公式並列実行は Cypress Cloud 前提。 Playwrightはワーカー指定だけ
- テスト名で「何が壊れたら落ちるか」を言語化する
- 1テスト = 1判断。 ログインは
storageState/cy.session()で前提に落とす - 安定性より説明可能性。 Trace Viewerや動画をCI成果物に残す
- リトライで緑になるテストの放置が、いちばん品質を下げる
PlaywrightやCypressは、境界を高速・確実に確認するための道具です。守る範囲を決めるのはツールではありません。
E2Eテストの品質は、テストが増えた瞬間ではなく、リリース判断が速くなった瞬間に分かります。
