Back to Blog
development·

Claude Codeでテスト駆動開発(TDD)を回す方法|Red-Green-Refactorの自動化

Claude CodeとTDD(テスト駆動開発)を組み合わせて、Red-Green-Refactorサイクルを効率的に回す方法を解説します。実際のプロンプトシーケンス、CLAUDE.mdでのTDDルール設定、品質メトリクスの追跡方法、TDDが機能しないケースまで具体例とともに紹介します。

#Claude Code#Claude Code 実践#TDD#テスト
Claude Codeでテスト駆動開発(TDD)を回す方法|Red-Green-Refactorの自動化

AIがコードを書く時代に、テストは不要になるのでしょうか。実際は逆です。AIが書いたコードは「おそらく正しい」が「確実に正しい」とは限りません。テストがなければ「おそらく」のまま本番に出ることになります。テスト駆動開発(TDD)はこの「おそらく」を「確実に」に変える手法であり、Claude Codeとの組み合わせで真価を発揮します。

本記事では、Claude CodeでTDDを実践する方法を、実際のプロンプトシーケンスからCLAUDE.mdの設定、品質メトリクスの追跡方法、そしてTDDが機能しないケースまで整理します。Claude Codeの基本についてはClaude Code完全ガイドを参照してください。

結論 — TDDはAIコーディングの「検証フレームワーク」になる

Claude CodeとTDDを組み合わせると、テストが「AIへの仕様書」として機能し、Red-Green-Refactorのサイクルを高速に回せます。 テストが先にあることで、Claude Codeの出力が「仕様を満たしているか」を機械的に判定でき、人間のレビュー負荷が大幅に下がります。

テストのないAIコーディングは「仕様書のない受託開発」と同じ構図です。何が正しいかの定義がないまま、コードだけが増えていきます。

なぜClaude CodeとTDDの相性がいいのか — 3つの理由

理由1: テストが曖昧さのない仕様書になる

「ユーザー登録機能を作って」と自然言語で指示するのと、「このテストがパスする実装を書いて」と指示するのでは、出力の精度が大きく異なります。

Before(自然言語の指示):

ユーザー登録のバリデーション関数を作って。
メールアドレスとパスワードをチェックして、
パスワードは8文字以上で。

この指示では「メールアドレスのフォーマットチェックはどこまで厳密に?」「8文字以上の上限は?」「バリデーション失敗時の返り値は?」が曖昧です。

After(テストで仕様を定義):

describe("validateUserRegistration", () => {
  it("正常なメールアドレスとパスワードの場合、successを返す", () => {
    const result = validateUserRegistration({
      email: "user@example.com",
      password: "SecureP@ss1",
    });
    expect(result).toEqual({ success: true, errors: [] });
  });

  it("メールアドレスが空の場合、エラーを返す", () => {
    const result = validateUserRegistration({
      email: "",
      password: "SecureP@ss1",
    });
    expect(result).toEqual({
      success: false,
      errors: [{ field: "email", message: "メールアドレスは必須です" }],
    });
  });

  it("パスワードが8文字未満の場合、エラーを返す", () => {
    const result = validateUserRegistration({
      email: "user@example.com",
      password: "short",
    });
    expect(result).toEqual({
      success: false,
      errors: [{ field: "password", message: "パスワードは8文字以上で入力してください" }],
    });
  });
});

このテストは、関数のインターフェース(引数と返り値の型)、正常系と異常系の挙動、エラーメッセージの文言まで定義しています。Claude Codeはこのテストを「完全な仕様書」として実装を生成します。

理由2: フィードバックループが自動で回る

Claude Codeはテストコマンドを自分で実行し、失敗すれば原因を分析し、コードを修正し、再テストを実行します。このループに人間の介入は不要です。

実行フロー:
Claude Code: テストを実行します → pnpm test -- validate-user.test.ts
結果: 3 tests, 1 passed, 2 failed
Claude Code: password のバリデーションが不足しています。修正します。
Claude Code: テストを再実行します → pnpm test -- validate-user.test.ts
結果: 3 tests, 3 passed
Claude Code: すべてのテストがパスしました。

理由3: リファクタリングが安全にできる

テストがある状態でリファクタリングを指示すれば、Claude Codeは「テストが通り続ける範囲で」コードを改善します。テストが壊れたら即座に検知できるため、安心して任せられます。

Red-Green-Refactor — 実際のプロンプトシーケンス

TDDの各フェーズで使用する具体的なプロンプトを示します。

Red フェーズ — 失敗するテストを書く

calculateScore関数のテストを先に書いて。まだ実装は書かないこと。

テストケース:
1. 正常系: [80, 90, 70] → 平均 80.0 を返す
2. 境界値: 空配列 → 0 を返す
3. 境界値: 要素が1つ [100] → 100.0 を返す
4. 異常系: null が含まれる [80, null, 70] → null をスキップして 75.0 を返す
5. 異常系: すべて null [null, null] → 0 を返す

テストファイルを作成したら、テストを実行して全テストが失敗することを確認して。

ポイント: 「まだ実装は書かないこと」と「全テストが失敗することを確認して」の2つの指示が重要です。Claude Codeは効率を優先して実装も同時に書こうとする傾向があるため、明示的に止める必要があります。

Green フェーズ — テストをパスする最小限の実装

先ほど作成した calculateScore のテストがすべてパスする最小限の実装を書いて。

制約:
- テストがパスすることだけを目標にする
- 過度な最適化やエラーハンドリングの追加は不要
- 関数は src/utils/calculate-score.ts に配置する
- テスト配置はコロケーション(同ディレクトリに calculate-score.test.ts)

実装後、テストを実行して全テストがパスすることを確認して。

Refactor フェーズ — テストを維持しながら改善する

calculateScore の実装をリファクタリングして。テストは全てパスし続けること。

改善観点:
- 関数が50行を超えていたら責務を分割する
- 命名をより明確にする(変数名、関数名)
- early return で読みやすくする
- 型安全性を向上させる(ReadonlyArray<T> の使用等)

リファクタリング後、テストを再実行してすべてパスすることを確認して。

Red-Green-Refactorの流れ

CLAUDE.mdでのTDDルール設定

CLAUDE.mdにTDDのルールを明記すると、毎回のプロンプトでTDD手順を伝える必要がなくなります。

推奨する設定(全文)

## TDD Workflow (MANDATORY)

### Process
1. RED: Write failing tests first. Run tests and confirm they FAIL before writing implementation.
2. GREEN: Write minimum implementation to pass tests. Run tests and confirm they PASS.
3. REFACTOR: Improve code quality while keeping all tests passing. Run tests after refactoring.

### Rules
- NEVER write implementation before tests
- NEVER skip the RED phase — always confirm test failure before implementation
- ALWAYS run tests after each phase (Red, Green, Refactor)
- New files require 80%+ test coverage
- Bug fixes MUST include a regression test (must FAIL before fix, PASS after fix)
- Do NOT mock the unit under test — only mock external dependencies

### Test Commands
- Run all: `pnpm test`
- Run single: `pnpm test -- path/to/file.test.ts`
- Run with coverage: `pnpm test -- --coverage`
- Watch mode: `pnpm test -- --watch`

### Test Conventions
- Collocate: `foo.test.ts` next to `foo.ts` (same directory)
- Describe block: function/component name
- Test names: Japanese, 「〜の場合、〜を返す」format
- One assertion per test (principle, not absolute rule)
- Edge cases required: null, undefined, empty array, boundary values, 0, MAX

### Mock Strategy
- External API calls → vi.mock()
- Database access → in-memory test repository
- Date/time → vi.useFakeTimers()
- File system → vi.mock("fs")
- NEVER mock the function under test

Before / After: CLAUDE.mdのTDDルール有無による出力の違い

Before(TDDルールなし):

「calculateScore関数を作って」と指示すると、Claude Codeはテストなしで実装を生成する。テストを追加で依頼すると、実装に合わせたテスト(= 実装の正しさを検証していないテスト)が生成される。

After(TDDルールあり):

同じ指示でも、Claude Codeが自発的にテストファーストで進める。「まずテストを書きます」→「テストが失敗することを確認しました」→「実装を書きます」→「全テストがパスしました」→「リファクタリングします」という手順を自動的に踏む。

品質メトリクスの追跡

TDDの効果を定量的に確認するために、以下のメトリクスを追跡することを推奨します。

カバレッジの追跡

# カバレッジレポートを生成
pnpm test -- --coverage

# 出力例:
# ----------------------|---------|----------|---------|---------|
# File                  | % Stmts | % Branch | % Funcs | % Lines |
# ----------------------|---------|----------|---------|---------|
# calculate-score.ts    |   95.24 |    88.89 |   100.0 |   95.24 |
# validate-user.ts      |   100.0 |   100.0  |   100.0 |   100.0 |
# ----------------------|---------|----------|---------|---------|

Hooksと組み合わせたカバレッジ監視

テストファイルが変更されるたびにカバレッジを自動チェックする設定です。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hook": "FILE=\"$CLAUDE_FILE_PATH\"; if echo \"$FILE\" | grep -q '\\.test\\.'; then DIR=$(dirname \"$FILE\"); SRC=$(echo \"$FILE\" | sed 's/\\.test\\.ts/.ts/'); [ -f \"$SRC\" ] && pnpm test -- --coverage \"$FILE\" 2>&1 | tail -10 || true; fi"
      }
    ]
  }
}

Gotcha: カバレッジ80%を目標にする場合の注意

「カバレッジを80%以上にして」とClaude Codeに指示すると、意味のないテスト(getterの戻り値を検証するだけのテスト等)が量産される傾向があります。カバレッジは「結果指標」であって「目標」ではありません。

より効果的な指示の例:

この関数の境界値テストを追加して。
特に、入力が空配列の場合と、要素がMAX_INT個ある場合の挙動を確認して。

このようにテストの内容を具体的に指示する方が、品質の高いテストが生成されます。

品質管理のコツ

バグ修正でのTDD活用 — Regression Testの実践

バグ修正にTDDを適用すると、再発防止テストが確実に作成されます。

プロンプトシーケンス

Issue #42: calculateScore が小数点以下の入力で誤った結果を返すバグ

ステップ1: まず、このバグを再現するテストを書いて。
入力 [79.5, 80.3, 70.2] で期待値 76.67 が返るべきところ、
現在は 76.66666... が丸められずに返る問題。
テストを実行して、失敗することを確認して。

ステップ2: テストがパスするようにバグを修正して。
修正後、テストを実行してパスすることを確認して。
既存のテストもすべてパスすることを確認して。

ステップ3: 修正コードをリファクタリングして。
テストを維持しながらコードを整理して。

なぜ「テストが失敗することを確認」が重要なのか

バグ修正時にredフェーズを省略すると、以下のリスクがあります。

  1. テストがバグを正しく再現していない可能性がある
  2. 修正前から既にテストがパスしていた場合、その修正は不要か、テストが不十分
  3. 将来同じバグが再発したとき、テストが検知しない可能性がある

TDDがClaude Codeで機能しないケース

TDDは万能ではありません。以下のケースでは別のアプローチが適切です。

1. UIコンポーネントの見た目の検証

「ボタンの角丸が4pxか」「フォントサイズが14pxか」のようなビジュアルテストは、単体テストでは限界があります。Visual Regression Testing(Chromatic、Playwright visual comparisons等)や、Storybook + 目視確認の方が効果的です。

2. 外部APIの統合テスト

外部APIの挙動をモックでシミュレートしても、実際のAPIの挙動と乖離するケースがあります。TDDで単体テストを書きつつ、E2Eテストやコントラクトテストを別途用意する必要があります。

3. 探索的な実装フェーズ

「どういうアーキテクチャにすべきかまだ決まっていない」段階でテストを先に書くのは困難です。プロトタイピング段階ではテストを後から追加し、設計が固まってからTDDに移行する方が実用的です。

4. Claude Codeがredフェーズをスキップする問題

Claude Codeは効率を優先して、テストと実装を同時に書こうとする傾向があります。CLAUDE.mdに NEVER skip the RED phase と書いていても、100%の遵守は保証できません。

Workaround:

まずテストだけ書いて。実装は絶対に書かないこと。
テストファイルだけを作成して、テスト実行結果を見せて。
実装は次の指示で依頼する。

プロンプトを2回に分けることで、redフェーズのスキップを物理的に防ぎます。

TDD + Subagents の組み合わせ

Subagentsにtesterエージェントを定義しておくと、TDDのワークフローがさらに安定します。

testerエージェントとの連携

# CLAUDE.md に追記
## Workflow
- テスト作成時は tester エージェントを使用すること
- テスト完了後のレビューは reviewer エージェントを使用すること

testerエージェントにTDDの手順を詳細に定義しておけば、「テストを書いて」の一言でredフェーズの確認まで含めた手順が自動的に実行されます。

TDDの効果を最大化するCLAUDE.mdの追加ルール

実運用で効果が確認できた追加ルールを紹介します。

## Test Quality Rules
- Test names must describe BEHAVIOR, not implementation
  - Good: "空配列の場合、0を返す"
  - Bad: "calculateScore_emptyArray"
- Each test must be independently runnable (no shared state between tests)
- Setup logic goes in beforeEach, not in individual tests
- Avoid testing private functions — test through public API
- When a test is flaky, fix the flakiness before writing new tests

よくある質問

まとめ — TDDでAIコーディングの品質を「仕組み」で担保する

Claude CodeとTDDの組み合わせは、AIが書いたコードの品質を機械的に保証する最も実用的なアプローチです。

  • テストを先に書くことで、AIへの指示が曖昧さのない「仕様書」として機能する
  • Red-Green-Refactorの各フェーズを明示的なプロンプトで制御する
  • CLAUDE.mdにTDDルールを記載すると、毎回の指示なしでTDDフローが回る
  • バグ修正にはregression testを必ず含め、redフェーズの確認を省略しない
  • UIの見た目検証や探索的実装にはTDDは不向き — 使い分けが重要
  • Hooksと組み合わせてカバレッジ監視を自動化すると効果が倍増する

AIがコードを書く量が増えるほど、テストによる品質保証の重要性は高まります。TDDは、その品質保証を開発プロセスに組み込む最も確実な方法です。

koromo からの提案

AIツールの導入判断は、突き詰めると「投資対効果が合うか」「リスクを管理できるか」「事業にどう効くか」の3点に帰着します。koromo では、この判断に必要な材料を整理するところからご支援しています。

以下のような状況にある方は、まず現状の整理だけでも前に進むきっかけになります。

  • AIで開発や業務を効率化したいが、自社に合う方法がわからない
  • 社内にエンジニアがいない / 少人数で、AI導入の進め方に見当がつかない
  • 外注先の開発会社にAI活用を提案したいが、何を求めればいいか整理できていない
  • 「AIを使えばコスト削減できるはず」と感じているが、具体的な試算ができていない

ツールを使った上で相談したい方はお問い合わせフォームから「Claude Code TDD 導入の相談」とご記載ください。初回の壁打ち(30分)は無料で対応しています。

本記事の更新方針: 本記事は定期的に内容を見直しています。記事内の判断軸・運用パターンは執筆時点での koromo の実務的知見に基づくものであり、個別環境での効果を保証するものではありません。仕様の最新情報は必ず Anthropic 公式ドキュメント をご確認ください。

Related Articles