tdd について
tddは、テストを先に失敗させてから最小限の実装で通す、テストファーストの開発手順を定めるスキルです。計画、テスト作成、実装、検証のエージェント順も示します。
主な機能
- 01本番コードより先に失敗するテスト
- 02Red-Green-Refactorの手順
- 03テストに基づく最小限の実装
- 04計画と検証を含むエージェント順序
- 05テストと全体の検証チェックリスト
活用シーン
- 01テストファーストで機能を実装
- 02バグ修正に回帰テストを追加
- 03TDDの各段階でエージェントを連携
- 04完了前に新旧テストを検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ parcadei/ continuous-claude-v3 --skill tddインストール後、Claude Code で/tddを入力して読み込まれたか確認します。
詳細
/tdd - テスト駆動開発ワークフロー
厳格なTDDワークフローです。まずテストを書き、その後に実装します。
使用するタイミング
- 「TDDでXを実装して」
- 「この機能をテストファーストで作って」
- 「Xのテストを書いてから実装して」
- テストカバレッジが重要な機能
- 回帰テストが必要なバグ修正
TDDの考え方
概要
まずテストを書きます。失敗することを確認します。テストを通す最小限のコードを書きます。
基本原則: テストが失敗するところを確認していなければ、そのテストが適切なものを検証しているかはわかりません。
ルールの文言に違反することは、ルールの精神に違反することです。
鉄の掟
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
テストより先にコードを書いた場合は、それを削除してやり直してください。
例外はありません:
- 「参考用」として残さない
- テストを書きながら「調整」しない
- 見ない
- 削除とは、削除することです
テストをもとに新たに実装してください。以上です。
レッド・グリーン・リファクター
RED - 失敗するテストを書く
何が起きるべきかを示す、最小限のテストを1つ書きます。
良い例:
test('retries failed operations 3 times', async () => {
let attempts = 0;
const operation = () => {
attempts++;
if (attempts < 3) throw new Error('fail');
return 'success';
};
const result = await retryOperation(operation);
expect(result).toBe('success');
expect(attempts).toBe(3);
});
明確な名前で、実際の動作を1つ検証しています。
悪い例:
test('retry works', async () => {
const mock = jest.fn()
.mockRejectedValueOnce(new Error())
.mockResolvedValueOnce('success');
await retryOperation(mock);
expect(mock).toHaveBeenCalledTimes(3);
});
曖昧な名前で、コードではなくモックを検証しています。
要件:
- 動作は1つ
- 明確な名前
- 実際のコードを使う(避けられない場合を除き、モックは使わない)
REDを検証 - 失敗することを確認する
必須です。絶対に省略しないでください。
npm test path/to/test.test.ts
# or
pytest path/to/test_file.py
次の点を確認してください:
- テストが失敗する(エラーではない)
- 失敗メッセージが想定どおり
- 機能がないために失敗している(タイプミスではない)
テストが通る場合は? 既存の動作をテストしています。テストを修正してください。 テストでエラーが発生する場合は? エラーを修正し、正しく失敗するまで再実行してください。
GREEN - 最小限のコードを書く
テストを通すための最もシンプルなコードを書きます。
良い例:
async function retryOperation<T>(fn: () => Promise<T>): Promise<T> {
for (let i = 0; i < 3; i++) {
try {
return await fn();
} catch (e) {
if (i === 2) throw e;
}
}
throw new Error('unreachable');
}
テストを通すために必要な分だけです。
悪い例:
async function retryOperation<T>(
fn: () => Promise<T>,
options?: {
maxRetries?: number;
backoff?: 'linear' | 'exponential';
onRetry?: (attempt: number) => void;
}
): Promise<T> {
// YAGNI - over-engineered
}
機能を追加したり、ほかのコードをリファクタリングしたり、テストの範囲を超えて「改善」したりしないでください。
GREENを検証 - テストが通ることを確認する
必須です。
npm test path/to/test.test.ts
次の点を確認してください:
- テストが通る
- ほかのテストも引き続き通る
- 出力がクリーン(エラーや警告がない)
テストが失敗する場合は? テストではなくコードを修正してください。 ほかのテストが失敗する場合は? すぐに修正してください。
REFACTOR - 整理する
グリーンになった後に限り、次の作業を行います:
- 重複を取り除く
- 名前を改善する
- ヘルパーを抽出する
テストが通る状態を保ってください。動作は追加しないでください。
よくある言い訳
| 言い訳 | 実際のところ |
|---|---|
| 「テストするほどでもなく簡単」 | 簡単なコードでも壊れます。テストは30秒で書けます。 |
| 「後でテストする」 | 最初からテストが通っても、何も証明できません。 |
| 「後からテストしても同じ目的を達成できる」 | 後からのテスト=「これは何をするのか?」。テストファースト=「これは何をするべきか?」。 |
| 「すでに手動でテストした」 | その場限りの確認は体系的なテストとは異なります。記録がなく、再実行もできません。 |
| 「X時間分を削除するのは無駄」 | サンクコストの誤謬です。検証されていないコードを残すのは技術的負債です。 |
| 「参考用に残して、先にテストを書く」 | そのコードに合わせてしまいます。それは後からのテストです。削除とは、削除することです。 |
| 「まず調査が必要」 | かまいません。調査用のコードは破棄し、TDDで始めてください。 |
| 「テストが難しいのは設計が不明瞭だから」 | テストの声に耳を傾けてください。テストしにくいものは、使いにくいものです。 |
| 「TDDでは遅くなる」 | TDDはデバッグより速いです。実践的に進めるなら、テストファーストです。 |
| 「手動テストのほうが速い」 | 手動テストではエッジケースを証明できません。変更のたびに再テストすることになります。 |
危険信号 - 作業を止めてやり直す
- テストより先にコードを書く
- 実装後にテストを書く
- テストがすぐに通る
- テストが失敗した理由を説明できない
- テストを「後で」追加する
- 「今回だけ」と正当化する
- 「すでに手動でテストした」
- 「後からテストしても同じ目的を達成できる」
- 「参考用に残す」または「既存のコードに合わせる」
これらはすべて、コードを削除してTDDでやり直すべきだという意味です。
検証チェックリスト
作業を完了とする前に、次を確認してください:
- 追加した関数/メソッドすべてにテストがある
- 実装前に、各テストが失敗することを確認した
- 各テストは想定どおりの理由で失敗した(タイプミスではなく、機能がないため)
- 各テストを通すための最小限のコードを書いた
- すべてのテストが通る
- 出力がクリーン(エラーや警告がない)
- テストには実際のコードを使用している(避けられない場合に限り、モックを使用)
- エッジケースとエラーを網羅している
すべてにチェックを付けられませんか? TDDを省略しています。最初からやり直してください。
行き詰まったとき
| 問題 | 解決策 |
|---|---|
| テスト方法がわからない | 望ましい API を書きます。まずアサーションを書きます。人間のパートナーに相談します。 |
| テストが複雑すぎる | 設計が複雑すぎます。インターフェースをシンプルにします。 |
| すべてをモックする必要がある | コードの結合度が高すぎます。依存性注入を使います。 |
| テストのセットアップが大規模 | ヘルパーを切り出します。それでも複雑ですか?設計をシンプルにします。 |
ワークフローの実行
ワークフローの概要
┌────────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐
│ plan- │───▶│ arbiter │───▶│ kraken │───▶│ arbiter │
│ agent │ │ │ │ │ │ │
└────────────┘ └──────────┘ └──────────┘ └───────────┘
Design Write Implement Verify
approach failing minimal all tests
tests code pass
エージェントの順序
| # | エージェント | 役割 | 出力 |
|---|---|---|---|
| 1 | plan-agent | テストケースと実装方針を設計する | テスト計画 |
| 2 | arbiter | 失敗するテストを書く(RED フェーズ) | テストファイル |
| 3 | kraken | テストを通す最小限のコードを実装する(GREEN フェーズ) | 実装 |
| 4 | arbiter | すべてのテストを実行し、問題がないことを確認する | テストレポート |
基本原則
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
各エージェントは TDD の契約に従います。
- arbiter は最初に必ず失敗するテストを書く
- kraken はテストを通すための最小限のコードを書く
- arbiter はテストスイート全体が通ることを確認する
実行
フェーズ 1:テストケースを計画する
Task(
subagent_type="plan-agent",
prompt="""
Design TDD approach for: [FEATURE_NAME]
Define:
1. What behaviors need to be tested
2. Edge cases to cover
3. Expected test structure
DO NOT write any implementation code.
Output: Test plan document
"""
)
フェーズ 2:失敗するテストを書く(RED)
Task(
subagent_type="arbiter",
prompt="""
Write failing tests for: [FEATURE_NAME]
Test plan: [from phase 1]
Requirements:
- Write tests FIRST
- Run tests to confirm they FAIL
- Tests must fail because feature is missing (not syntax errors)
- Create clear test names describing expected behavior
DO NOT write any implementation code.
"""
)
フェーズ 3:実装する(GREEN)
Task(
subagent_type="kraken",
prompt="""
Implement MINIMAL code to pass tests: [FEATURE_NAME]
Tests location: [test file path]
Requirements:
- Write ONLY enough code to make tests pass
- No additional features beyond what tests require
- No "improvements" or "enhancements"
- Run tests after each change
Follow Red-Green-Refactor strictly.
"""
)
フェーズ 4:検証する
Task(
subagent_type="arbiter",
prompt="""
Validate TDD implementation: [FEATURE_NAME]
- Run full test suite
- Verify all new tests pass
- Verify no existing tests broke
- Check test coverage if available
"""
)
適用される TDD ルール
- arbiter は実装コードを書けません
- kraken はテストされていない機能を追加できません
- 実装前にテストが失敗しなければなりません
- 実装後にテストが成功しなければなりません
例
User: /tdd Add email validation to the signup form
Claude: Starting /tdd workflow for email validation...
Phase 1: Planning test cases...
[Spawns plan-agent]
Test plan:
- Valid email formats
- Invalid email formats
- Empty email rejection
- Edge cases (unicode, long emails)
Phase 2: Writing failing tests (RED)...
[Spawns arbiter]
✅ 8 tests written, all failing as expected
Phase 3: Implementing minimal code (GREEN)...
[Spawns kraken]
✅ All 8 tests now passing
Phase 4: Validating...
[Spawns arbiter]
✅ 247 tests passing (8 new), 0 failing
TDD workflow complete!
リファクタリングフェーズ(任意)
GREEN の後に、リファクタリングフェーズを追加できます。
Task(
subagent_type="kraken",
prompt="""
Refactor: [FEATURE_NAME]
- Clean up code while keeping tests green
- Remove duplication
- Improve naming
- Extract helpers if needed
DO NOT add new behavior. Keep all tests passing.
"""
)