CLAUDE LABEN
FORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられていますFORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられています
記事一覧/Claude Code
Claude Code/2026-04-26上級

Claude Code でテスト駆動開発を実装する — エージェントと書く TDD ワークフロー

Claude Code に「先にテストを書いてもらう」という制約を加えると、エージェントの暴走が止まり、生成コードの質が劇的に変わります。私が半年間試行錯誤して辿り着いた、エージェント時代の TDD ワークフローを共有します。

Claude Code198TDD4テスト駆動開発エージェント13ワークフロー20ソフトウェア設計2

Claude Code を本格的に使い始めて半年ほど経った頃、私は同じ壁に何度もぶつかっていました。指示は通っているはずなのに、生成されたコードを git diff で開くと、頼んでもいないファイルが書き換わっています。テストは通っているのに、レビューしてみると仕様を微妙に取り違えています。あるいは、リファクタリングをお願いしたら関数の振る舞いごと変わっていた、というやつです。

最初は「プロンプトの書き方が悪い」「もっと詳細な仕様書を渡そう」と考えていましたが、だんだん別の仮説に行き着きました。エージェントには「ゴールが何なのか」を機械的に判定できる仕組みが必要なのではないか、ということです。

人間の開発者は頭の中に「このコードが正しい状態」のイメージを持っていて、書きながら絶えず照合しています。Claude Code にもプロンプトでイメージを伝えてはいるのですが、それは曖昧で、しかも会話の途中で揺らぎます。一方、テストコードは「合否を機械的に判定できる仕様」です。先にこれを書いてしまえば、エージェントは「テストが通る」という明確な目標に向かって作業できます。

これに気づいてから、私は Claude Code でのほぼすべてのタスクを TDD ベースに切り替えました。結果として、エージェントの暴走は激減し、コードレビューに使う時間は半分以下になり、何より自分自身が安心して任せられるようになりました。今回はその実践方法を、失敗例も含めて共有します。

なぜエージェント時代こそ TDD が効くのか

従来の TDD が広く受け入れられなかった理由のひとつに、「テストを先に書くのは面倒」という心理的コストがありました。実装したいコードのイメージはすぐに浮かぶのに、それをわざわざテストとして言語化するのは、二度手間に感じられたわけです。

ところが Claude Code が登場したことで、この前提が崩れました。テストコードを書く労力こそ、エージェントに最も任せやすい作業だからです。仕様を日本語で説明すれば、それに対応する Vitest や Jest、pytest のテストケースを 30 秒で生成してくれます。私が手で書くと 30 分かかるテストが、対話 3 ターンで揃います。

そして書かれたテストには、もうひとつ重要な役割があります。「Claude Code 自身に対する仕様書」になるのです。テストファイルを開いた状態で実装を依頼すると、エージェントはまずテストを読み、そこから求められている振る舞いを正確に把握します。プロンプトで仕様を伝えるよりも、テストを通じて伝えるほうが、解釈のブレがはるかに小さいのです。

もうひとつ実感している効果は、「エージェントが過剰な作業をしなくなる」ことです。テストが通ってさえいれば良いという明確なゴールがあると、Claude Code は関係ないファイルに手を出さなくなります。これは Anthropic の公式ドキュメントには書かれていない、実践してみて初めて気づいた挙動でした。

私が辿り着いた TDD ワークフローの全体像

私が現在使っているフローは次の 5 ステップです。各ステップは Claude Code に任せられる部分と、人間が判断すべき部分に明確に分かれています。

最初のステップは「仕様を会話で固める」フェーズです。実装したい機能をぼんやりと話しながら、Claude Code に「この機能の境界条件、エッジケース、想定される失敗パターンを列挙してください」と頼みます。ここで出てきたリストを見ながら、自分の中で曖昧だった部分を詰めます。これは人間が考えるパートです。

次のステップで、固まった仕様をもとに「失敗するテスト」を書いてもらいます。ポイントは、テストファーストの原則どおり、テストの段階では実装ファイルが存在しないか、関数のシグネチャだけが定義されている状態にしておくことです。npm test を実行して、テストが赤になることを確認します。これが TDD でいう「Red」フェーズですね。

3 番目に、テストを通すための最小実装をエージェントに依頼します。ここで重要なプロンプトテクニックがあります。「以下のテストファイルを通すための最小限の実装を src/foo.ts に書いてください。テストファイルや他のファイルは絶対に変更しないでください」と明示的に書きます。これで実装ファイルだけが触られ、テストの改ざんによる「ズルい合格」を防げます。

4 番目はリファクタリングです。テストが緑になった状態で、Claude Code に「テストを通したまま、可読性と保守性を高めるリファクタリングをしてください」と依頼します。ここでもテストファイルは触らせません。リファクタリング前後でテストが通り続けていれば、振る舞いが保たれている証明になります。

最後の 5 番目で、人間がコードレビューします。ただし、レビュー対象は実装コードと新しく追加されたテストの両方です。テスト自体が仕様の妥当性を担保しているか、エッジケースを十分カバーしているかを確認します。

Claude Code に渡すプロンプトの実例

抽象論だけでは伝わりにくいので、私が実際に使っているプロンプトテンプレートを共有します。これは TypeScript + Vitest プロジェクトでの例ですが、他言語でも応用できます。

仕様検討フェーズで使っているプロンプトはこんな感じです。

これから「ユーザーのメールアドレスをバリデーションする関数」を実装したい。
以下を列挙してください:
1. 期待される正常系の入力例 (3 つ以上)
2. 拒否すべき異常系の入力例 (5 つ以上)
3. 仕様として曖昧な境界ケース (例: サブアドレス記法、国際化ドメイン名)
4. テストとして書くべきだが見落としがちなケース

実装は不要です。リスト形式で答えてください。

返ってきたリストを眺めて、自分の頭にあった仕様の穴を埋めます。たとえば「クォーテーション付きローカル部はサポートする?」のような問いに、自分なりに答えを決めます。

仕様が固まったら、テスト生成プロンプトに移ります。

以下の仕様に対応する Vitest テストを `src/utils/email-validator.test.ts` に書いてください。

仕様:
- 関数名: validateEmail(input: string): { ok: true } | { ok: false; reason: string }
- RFC 5321 のドット表記ローカル部のみ受け入れる
- サブアドレス記法 (foo+bar@example.com) は受け入れる
- 国際化ドメイン名は punycode 変換後の形式のみ受け入れる
- 拒否時は reason に "missing-at" / "invalid-local" / "invalid-domain" のいずれかを返す

制約:
- 実装ファイル `src/utils/email-validator.ts` は、export 文だけのスケルトンを作成してください
- テスト数は最低 12 ケース、describe で分類してください
- まだ実装していないことを前提に、テストが赤になる状態で OK です

このあとに npm test -- src/utils/email-validator.test.ts を実行すると、当然全件失敗します。これが Red の状態です。

次に実装プロンプトに移ります。

`src/utils/email-validator.ts` に validateEmail を実装してください。
すべてのテストが緑になる必要があります。

絶対に守ること:
- テストファイル `src/utils/email-validator.test.ts` は読み取り専用として扱う。1 文字も変更しない
- 他のファイル (package.json、他の utils など) も変更しない
- 外部依存の追加は不可。Node.js 標準と TypeScript 標準ライブラリのみで実装

完了したら `npm test -- src/utils/email-validator.test.ts` を実行し、結果を報告してください。

「絶対に守ること」のセクションがないと、Claude Code は時々「テストの方が間違っているように見えます」と言ってテストを書き換えに来ます。これは TDD の原則に反するので、明示的に禁止します。

エージェントの暴走を防ぐフックとパーミッション設計

Claude Code には Hooks 機能があり、ファイルへの書き込み前後にスクリプトを差し挟めます。私は TDD ワークフロー専用のフックを .claude/settings.json に組み込んでいます。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "node .claude/hooks/protect-test-files.mjs"
          }
        ]
      }
    ]
  }
}

protect-test-files.mjs は標準入力から JSON を受け取り、書き込み対象が .test.ts または .spec.ts で終わっていて、かつ環境変数 TDD_PHASEred でない場合にエラーで終了します。これにより、実装フェーズやリファクタリングフェーズでテストファイルが誤って改変されるのを防げます。

#!/usr/bin/env node
import { readFileSync } from "node:fs";
 
const input = JSON.parse(readFileSync(0, "utf-8"));
const filePath = input?.tool_input?.file_path ?? "";
const phase = process.env.TDD_PHASE ?? "implementation";
 
const isTestFile = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filePath);
 
if (isTestFile && phase !== "red") {
  console.error(
    `[TDD Guard] テストファイル ${filePath} の編集はブロックされました。\n` +
    `現在のフェーズ: ${phase}\n` +
    `テスト追加・修正が必要な場合は TDD_PHASE=red claude を起動してください。`
  );
  process.exit(2);
}

この仕組みを入れる前は、リファクタリング中に「ついでにテストもきれいにしておきます」と Claude Code が善意でテストを書き換え、本来検出すべきだったバグが通ってしまった、というインシデントが何度かありました。今は構造的に防がれています。

リファクタリングをエージェントに任せるときの注意点

TDD の最後のステップ、リファクタリングは、Claude Code に任せると最も恩恵が大きいフェーズです。しかし同時に、最も慎重なプロンプト設計が必要なフェーズでもあります。

私が経験した失敗のひとつは、「テストを通したまま、もっと良いコードに書き直してください」という雑なプロンプトで依頼したケースです。Claude Code はテストを通したまま、関数のシグネチャを変えて呼び出し側もまとめて書き換えてしまいました。テストは通っているので形式的には正しいのですが、API の互換性が失われ、他のモジュールが壊れていました。

今は次のような制約付きでお願いしています。

`src/utils/email-validator.ts` をリファクタリングしてください。

目的:
- 早期 return を増やしてネストを浅くする
- 正規表現の意図を変数名で説明する

絶対に守ること:
- 関数 validateEmail のシグネチャと公開 API は変更しない
- テストファイルは変更しない
- 関数の追加は OK だが、既存関数の名前変更や削除は不可
- 他ファイルは変更しない

完了したら、変更点を箇条書きで報告し、テストが全件通っていることを示してください。

「目的」を絞ること、「絶対に守ること」で外形を固定すること、この 2 つがリファクタリング成功の鍵です。

TDD 化前後で変わったメトリクス

私が個人で運営している中規模のサイトのコード(TypeScript で約 4 万行)を、3 ヶ月かけて TDD 化しました。それまでは「動いているからヨシ」で進めていた部分にも、後付けでテストを足していきました。Claude Code を使ったので、無理なく進められました。

その前後で、いくつかの数字が目に見えて変わりました。コードレビューで「ここは何をしているコードですか」とエージェントに質問する回数が、月平均 40 回から 8 回に減りました。テストを読めば仕様がわかるので、実装コードの理解にかかる時間が短縮されたのです。

本番環境で発生したバグの数も減りました。3 ヶ月で 11 件あった production バグが、TDD 化後の 3 ヶ月では 3 件です。残った 3 件はいずれも、テストが書かれていなかったエッジケースに起因していました。テストの「網」をすり抜けたバグのみが残ったわけで、TDD の効用としては想定通りでした。

予想外だったのは、Claude Code に支払う API コストがやや上がったことです。テストと実装で 2 段階に分けるぶんだけ、トークン消費が増えるからです。月のコストで 1.3 倍くらいになりました。ただ、自分の時間が大幅に節約されているので、トータルでは大きなプラスだと感じています。

TDD が向かないケース、向くケース

正直に書くと、すべてのタスクに TDD が向くわけではありません。私が「TDD なしで Claude Code に頼む」と決めているのは、次のような場合です。

ひとつは、UI のプロトタイピングです。Tailwind と React で見た目を試行錯誤するフェーズでは、テストを先に書いてもむしろ足枷になります。ここはスナップショットテストやビジュアルリグレッションテストの方が向くので、TDD は適用しません。

もうひとつは、データ探索や 1 回限りのスクリプトです。CSV を加工して 1 度だけ集計を出すような作業に、テストを書く意味はあまりありません。

逆に TDD が劇的に効くのは、「振る舞いが明確に定義できるロジック」を扱うときです。バリデーション、パース、計算、状態遷移、API のレスポンス整形など、入出力が明示できるものはすべて対象です。私のサイトでいうと、Stripe の Webhook ハンドラ、料金プランの判定ロジック、記事メタデータの抽出ツールなどはすべて TDD 化されており、その後ほぼ手を加えていません。

明日から始めるための具体的な一歩

長くなったので、最後に明日から試せる最小ステップを 1 つだけ挙げます。

今のプロジェクトで、最近触ったばかりで自信のないコードを 1 つ選んでください。そのコードに対して、Claude Code にこう頼んでみます。

`src/foo.ts` の現在の振る舞いを推測し、Vitest テストを `src/foo.test.ts` に書いてください。
コードは変更しないでください。テストは現状の振る舞いを documentation として記述する目的です。

これは TDD というより「特性化テスト」と呼ばれる手法ですが、Claude Code 時代の TDD への入り口として最適です。生成されたテストを読めば、自分が書いたコードの振る舞いを Claude Code がどう理解しているかが見えます。理解が間違っていたら、それは仕様が曖昧な証拠です。理解が正しければ、テストが残るので、次に変更するときの安全網になります。

ここから少しずつ、新規コードに対して「テストを先に書いてもらう」習慣を加えていけば、半年後には私と同じく「もう TDD なしの Claude Code は怖くて使えない」状態になっているはずです。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

Claude Code2026-04-24
Claude Code にバグ修正を任せる前に書くべき「再現テスト」— AIの無駄打ちを減らす設計
Claude Code にバグ修正を丸投げして空回りした経験を踏まえ、最初に「落ちる再現テスト」を書いてから委譲するワークフローを、運用している設計原則と具体的なコードで整理します。
Claude Code2026-04-17
「仕様書がテストになり、テストが実装になる」 — Claude Code で実現する Spec-Driven Development
仕様書を書くだけで Claude Code がテスト・実装・ドキュメントを自動生成する Spec-Driven Development の実践ガイド。YAML仕様フォーマット・TDD自動化・CI/CD統合まで、実際のコードで体系的に解説します。
Claude Code2026-06-24
Claude Design と Claude Code を行き来して作る — 発散と収束を分担する開発の流れ
デザインの大枠は Claude Design で、細部の作り込みは Claude Code で。デスクトップアプリへ統合されて往復しやすくなった2つを、発散と収束で役割分担する開発の進め方として整理します。Link Local code と Send to の橋渡しまで。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →