Claude Codeのテスト自動化。システムテストは必要なのか
前回の記事で、/test-itスキル(結合テスト自動生成)を実プロジェクトで試した。specとの照合で漏れを見つけ、UTとITの境界も整理した。
次はシステムテスト(ST)だ。ITの上の層だからSTスキルを作ろう——そう思ってリサーチを始めたら、「ST」はE2Eに吸収されていた。 そしてE2E(End-to-End)テスト——ユーザーの操作フローを丸ごとブラウザで再現するテスト——の正しいスコープは、自分が思っていたものと全く違った。
STはE2Eに吸収されていた
ITの次はST。自然な発想だった。ISTQB(International Software Testing Qualifications Board、ソフトウェアテストの国際資格団体)の教科書的な4層モデル(UT → IT → ST → 受入テスト)を頭に入れていたから。
でも「STとは何か」を真面目にリサーチしたら、話が変わった。
ISTQBの定義ではSTとE2Eは別物だ。STは「単一システムの要件検証」、E2Eは「複数システム横断のワークフロー検証」。ここまでは教科書通り。
ところが、実務で使われているテスト戦略モデルを並べてみると景色が違う。
| モデル | 提唱者 | 層構成 | STの扱い |
|---|---|---|---|
| Testing Pyramid | Mike Cohn (2009) | Unit > Service > UI | Service層にST含む |
| Testing Trophy | Kent C. Dodds (2018) | Static / Unit / Integration / E2E | STは存在しない |
| Testing Diamond | 複数 (2020s) | Unit / Integration / E2E | STは存在しない |
| Testing Honeycomb | Spotify (2018) | Impl Detail / Integration / Integrated | STは存在しない |
Pyramid以外の全モデルが「ST」を独立した層として持っていない。STの役割はE2Eに吸収されている。
Martin Fowlerの言葉が刺さった。「テストカテゴリについて議論する際は、相手がその言葉で何を意味しているかを掘り下げよ」。用語の定義争いより、テストが何を検証するかに集中すべきだと。
結論: /test-stではなく/test-e2eとして設計する。
BDD/Gherkinは要らなかった
E2Eテスト生成で最初に思い浮かぶのはBDD(Behavior-Driven Development)。Given/When/Then形式でシナリオを書き、Cucumber等のフレームワークでテストコードに変換する流れだ。
でも調べたところ、BDDフレームワーク自体が衰退期にあった。
- SpecFlow: 2024年にEOL(End of Life)。開発終了
- Cucumber: SmartBearが手放し、コミュニティ主導に。停滞気味
なぜ衰退したのか。リサーチで見つけた金融機関の事例が象徴的だった。Gherkinのステップ定義メンテナンスに開発工数の3倍が消費され、最終的に放棄された。 Feature → Step Definition → Page Objectの3層を維持するコストが、テスト自体の価値を上回ってしまう。
そもそもBDD/Gherkinの価値は「人間が読める仕様」にあった。でも自分のワークフローではspec.md自体がGiven/When/Then形式で書かれている。LLMはspecを直接理解できるから、Gherkinという中間翻訳層を挟む理由がない。
spec.md → LLM直接変換 → Playwrightテストコード。 この1ステップが2025-2026年の最適解だと判断した。
カンニング防止をE2Eでどう実現するか
10回目の記事で書いた「カンニング防止」。AIにテストを書かせるとき、実装コード(src/)を見せると実装に寄り添ったテストになり、仕様との乖離を見逃す問題だ。
/test-itではClaude CodeのTask tool(別コンテキストでサブタスクを実行する機能)を使い、specだけ渡して実装コードを見せない1段階方式で解決した。
E2Eはブラウザ操作が必要なので、同じ方式は使えない。セレクタ情報(画面のどのボタンを押すか等)がなければテストが書けない。かといってsrc/を見せたらカンニング防止が崩れる。
2段階アーキテクチャで解決した。
Step 1(メインコンテキスト): Playwright MCP(ブラウザ操作用のツール)でアプリを探索し、画面構造やボタン・入力欄のセレクタ情報をpage-map.mdに書き出す。
Step 2(Task tool): spec + page-map.mdだけを渡してテストコードを生成。src/は見えない。
AIがテスト生成時に見ていいもの、見てはいけないものを明確に分けた。見せないのはsrc/(実装コード)だけ。 それ以外の情報源でテストに必要な知識を渡す。
- spec(仕様書)
- page-map.md(セレクタ情報)
- ARCHITECTURE.md(設計ドキュメント)
- DOM / アクセシビリティツリー
最初の設計は間違っていた
ここまでで「カンニング防止」と「ブラウザ操作」の両立はできた。/test-itと同じノリで「specの全User Story(US)と全Edge Case(EC)をE2Eでカバーしろ」とスキルに書いた。
これが間違いだった。
E2Eには、ITにはない3つの問題がある。
1. 壊れやすさ(Flaky Tests)
ITはインプロセスで動く。ネットワークもブラウザも介在しない。E2Eは違う。ブラウザの起動、ネットワーク通信、アニメーション、非同期ロード——全部が変数になる。バグがないのにテストが落ちる。いわゆるFlaky Test(不安定なテスト)だ。
「たまに落ちるテスト」が混ざると、チームはテスト結果を信用しなくなる。
2. メンテナンスコスト
UIが変わるたびにセレクタの更新が発生する。ボタンのラベル変更、フォーム構造の変更——その都度テストコードに手を入れる必要がある。先述の金融機関事例では、ステップ定義のメンテナンスが開発の3倍のコストに膨らんでいた。
3. スコープ肥大
全US/ECをE2Eでカバーしようとすると、テストスイートが肥大化する。巨大なE2Eスイートは実行が遅く、壊れやすく、直す気力も湧かない。行き着く先は「全部無視してデプロイ」だ。
E2Eは煙テストだった
じゃあE2Eで何をテストするのか。
煙テスト(Smoke Test)。 アプリの最も重要な経路が動くことだけを確認する。ログインできるか。メインの操作フローが通るか。決済が完了するか。「煙が出ていないか」を確認するテストだ。
修正後のスコープルールはこうなった。
| 対象 | E2Eでテストする? |
|---|---|
| クリティカルパスのP1(最優先)User Story | する |
| P2以下のUser Story | しない。ITでカバー |
| Edge Case | しない。ITでカバー |
| 非機能要件(性能、セキュリティ) | しない。専用ツールで |
Edge CaseはITに任せる。 /test-itはインプロセスで動くからFlaky Testにならないし、実行も速い。E2Eは「メインの道が通るか」だけに集中させる。
テストデータと環境の4課題
スコープを絞っても、E2Eには環境まわりの課題が残った。
| 課題 | 内容 |
|---|---|
| テストデータ | フロントエンド(localStorage等)とバックエンド(DB等)の2層をどうセットアップするか |
| 認証フロー | ログインの方式はプロジェクトごとに違う。storageStateの事前保存等 |
| page-mapの鮮度 | UI変更後にセレクタ情報が古くなる。いつ再探索するか |
| APIモック方針 | 外部APIをモックするか実際に叩くかはプロジェクト依存 |
これらは実装の詳細だから、src/を見ないと解決できない——と最初は思った。
でもよく考えると、認証方式やデータ層の構成は設計ドキュメント(ARCHITECTURE.md)に書いてある情報だ。実装コードを直接見なくても、設計レベルの情報があればテストのセットアップは書ける。
ARCHITECTURE.mdをTask toolに渡す対象に追加。 カンニング防止を維持しつつ、環境情報を渡す方法が見つかった。
テスト戦略の全体像
ここまでで、AI開発フロー全体のテスト戦略が整理できた。
各層が何を検証するか。
| テスト層 | 誰が実行 | 何を検証するか |
|---|---|---|
| UT | Agent Teams内のQA担当 | 1モジュール単体の振る舞い。障害の切り分け |
| IT |
/test-itスキル |
モジュール間のデータ受け渡し。specの全US/EC |
| E2E |
/test-e2eスキル |
クリティカルなユーザーフロー(煙テスト) |
| コードレビュー |
/reviewスキル |
コード品質、設計の一貫性 |
| モンキーテスト | 人間 | 想定外の操作、AIが見逃すUXの違和感 |
人間がやるのはモンキーテストだけ。 「適当に触ってみて変なところがないか」——これはAIが最も苦手で、人間が最も得意な領域だ。
/test-itとの設計比較
最後に、/test-it(IT)と/test-e2e(E2E)の設計を並べてみる。
| /test-it (IT) | /test-e2e (E2E) | |
|---|---|---|
| 入力 | spec + plan | spec + page-map + ARCHITECTURE.md |
| スコープ | specの全US/EC | クリティカルパスのP1 USのみ |
| Edge Case | カバーする | やらない(ITに任せる) |
| 隔離方式 | Task tool 1段階 | 2段階(MCP探索 → Task toolでテスト生成) |
| カンニング防止 | src/を見せない | src/を見せない。page-map経由でUI情報だけ渡す |
| テストランナー | Vitest / Jest | Playwright Test |
| 実行環境 | インプロセス | ブラウザ |
| Flaky Testリスク | 低い | 高い(だからスコープを絞る) |
共通しているのは「src/を見せない」「specを基準にする」という原則。違うのはスコープの考え方だ。ITは網羅性、E2Eは選択と集中。
まとめ
| 学び | 内容 |
|---|---|
| STという層は要らない | Testing Trophy/Diamond/Honeycombのどれも「ST」を持たない。E2Eに吸収されている |
| E2Eは煙テスト | 全仕様をカバーしようとすると壊れる。クリティカルパスだけ。Edge CaseはITに任せる |
| カンニング防止はE2Eでも維持できる | 2段階アーキテクチャ(MCP探索 → Task toolでテスト生成)でsrc/を見せずにブラウザテストが書ける |
| BDD/Gherkinは不要 | LLMがspecから直接テストコードを生成できる。中間翻訳層のメンテコストを払う理由がない |
「ITの次はST」という教科書的な発想から始めて、リサーチで軌道修正し、最初の設計ミス(全仕様E2Eカバー)も修正した。テスト設計は「何をテストするか」より「何をテストしないか」の判断が難しい。 E2Eでは特にそうだった。
Discussion