はじめに
「Claude Codeにテストも書かせているが、いつも実装の後にテストが来る」——これはClaudeのデフォルト動作による問題だ。
Claude Codeは何も言わなければ実装ファーストで動く。テストを依頼しても、内部では「どう実装するか」を考えながらテストを書くため、テストが実装の設計に合わせた形になる。これがコンテキスト汚染問題だ。
「テストが先」を守らせることで、テストが実装の設計図になり仕様のブレを防げる。バグを「作った瞬間」に検知できる。AIが自律的にテスト→実装→テストのループを回せるようになる。TDDの価値はAI時代でも変わらない。むしろ「AIが生成したコードの品質保証」として重要性が増している——「AIが書いたコードだから信用できない」という不安を、テストが解消する。AI駆動TDDでは、テストを「永続的な資産」ではなく「AIへの自律評価手段を与えること」として捉えると使いやすい。
なぜClaudeはTDDを守らないのか:コンテキスト汚染問題
TDDの本質は「実装を知らない状態でテストを書く」ことにある。ところが単一のコンテキストウィンドウで「テストを書いて→実装して」を依頼すると、構造的な問題が起きる。
テスト作成フェーズ
↓ この時点でClaudeは「どう実装するか」を考えている
テストが「実装案に最適化」された形で生成される
↓
実装フェーズ
↓ テスト作成時の判断がそのまま引き継がれる
実装もテストも同じ前提から生まれ、整合性だけが確保される
↓
実装の「抜け道」を許したテストが出来上がる
テストの役割は「実装の正しさを独立に検証すること」だが、同じコンテキストで生成されたテストはその独立性を失う。何も指示しなければ実装コードを書いてからテストを追加するし、「TDDで実装して」と言っても60〜80%のケースで先に実装が始まる(Hooks未使用時)。
アプローチ1:プロンプトでTDDを明示する(最もシンプル)
特別な設定なしに今すぐできる最初の一歩だ。
「TDDでテストだけ書いて。実装は書かない。モック実装も作らない。
テストを実行して落ちることを確認して」
「TDDで実装して」ではなく「テストだけ書いて」と明示することで先走りを防ぐ。より確実にするための4ステップのプロンプトシーケンスはこうなる。
Step 1(テスト作成):
「このAPIエンドポイントのテストだけを書いて。実装は書かない。
入出力の期待値を定義したら、テストを実行して失敗を確認して」
Step 2(テストコミット):
「テストが落ちることを確認した。今のテストをコミットして。
実装はまだ始めないで」
Step 3(実装):
「テストを一切変えないで、全てのテストが通るまで実装→テストを反復して」
Step 4(検証):
「この実装、テストに過剰適合してない?抜け道ない?
コード証拠なしの推測は禁止で、各指摘に確信度を付けて報告して」
プロンプトで効果を高める工夫:「t-wadaの推奨する進め方に従ってください」と指定するとTDDの実施率が大幅に向上することがわかっている(GMOペパボ2025年技術講演)。Claude Codeは学習データからt-wada氏のTDD実践知識を持っているため、権威ある方法論を参照させることで体系的なRed-Green-Refactorが実行される。
CLAUDE.mdへの記述でデフォルト化:
## TDDルール
- 実装コードの前に必ずテストを書く
- テストが失敗することを確認してからコミット
- テストをコミットしてからセッションを分けて実装を行う
- 実装中はテストコードを変更しない
この記述があると、「実装して」という指示でもClaude Codeが自動的にテストファーストで動き始める。
アプローチ2:TDD Enforcer Skill
プロンプトに頼らず、Skillsファイルにワークフローそのものを定義してしまう方法だ。
# ~/.claude/skills/tdd-enforcer.md
機能リクエストのたびに以下の手順を必ず踏むこと:
1. 要件の明確化(何を実現するか・しないかを確認)
2. テストケースの先行生成(正常系・異常系・境界値を網羅し、失敗を確認)
3. テストカバレッジのレビュー(ユーザー承認を求める・ここで止める)
4. 実装コードの作成(ユーザー承認後のみ・テストを通す最小実装)
5. 全テスト通過の確認(新規テスト + 既存テストの両方)
6. 統合テストの生成
絶対NG:テストを書く前に実装コードを書くこと
このスキルを90日間運用したある個人エンジニアの実践報告(aihero.devによる参考値)では、本番バグ数70%削減(Sentry計測)、テストカバレッジ40%→90%、デバッグ速度50%高速化という結果が出ている。
アプローチ3:HooksによるRed-Green-Refactor完全自動化
最も強力な方法だ。SkillsはClaude Codeが従う「努力目標」だが、Hooksは「ルール違反時にシステムが止める」強制力を持つ。
TDD Guard(GitHub: nizos/tdd-guard)のアプローチでは、実装ファイルが作成・変更されるときに PreToolUse フックが発動し、対応するテストが事前に存在しなければ変更をブロックする。さらにサブエージェントを使った完全分離も実現できる。
[REDフェーズ] テスト作成サブエージェント
↓ 機能要件を受け取る・テストケースのみを生成
↓ テストが失敗することを確認してコミット
[GREENフェーズ] 実装サブエージェント(別コンテキスト)
↓ テストコードのみを受け取る(実装計画なし)
↓ テストを通す最小実装を作成
[REFACTORフェーズ] リファクタリングサブエージェント
↓ テストがgreenを保ちながら構造を改善
各フェーズが独立したコンテキストで動くため、REDフェーズの「実装アイデア」がGREENフェーズに流入しない。コンテキスト汚染を根本から防ぐ設計だ。
Hooksの設定が複雑に感じる場合、セッションを手動で分けるだけでも効果がある。
Session 1: 「TDDでテストだけ書いて。実装は書かない」→ テストをコミット → セッション終了(重要)
Session 2: 「このテストを全て通す実装を書いて」→ 実装をコミット
セッションを分けるだけで、テストと実装が「独立した視点」から生まれる効果がある。
ビフォーアフター
Before(TDDなし)
「この機能を実装して」と指示すると、Claudeが実装してから後でテストを追加する。テストが実装の形に合わせて書かれるため独立性はゼロで、本番でエッジケースのバグが発生して「なぜテストで検知できなかったのか」という状況になる。
After(TDD Enforcer Skill + セッション分離)
Session 1で「TDDでテストだけ書いて」→テスト作成→失敗確認→コミット。Session 2で「このテストを通す実装を書いて」→実装→テスト通過→コミット。テストが「実装を知らない視点」から書かれているため、エッジケースが実装ファーストより確実に網羅される。90日実測で本番バグ70%削減(aihero.devによる参考値)。
まとめ:今日からできること
難易度の低い順に並べてあるので、上から試してほしい。
1. 今すぐ(1分): 次の実装タスクで「TDDでテストだけ書いて。実装は書かない」を試す
2. 今日中: CLAUDE.mdに「実装コードの前に必ずテストを書く」ルールを追記する
3. 今週: ~/.claude/skills/tdd-enforcer.md にTDD Enforcer Skillを作成する
4. 本格運用: セッション分離パターン(テストコミット→新セッションで実装)を習慣化する
「AIが書いたから品質が低い」という不安を手放せるようになる——そのための仕組みがClaude Code × TDDだ。

コメント