tdd について
tddは、テスト駆動開発を導くスキルです。パブリックインターフェースを通じて観察可能な振る舞いを検証し、テスト一つと最小限の実装を一組として進めます。実装前にインターフェース、テストの優先順位、設計境界を確認します。
主な機能
- 01パブリックインターフェースで振る舞いを検証
- 02テスト一つずつRED→GREENで進行
- 03現在のテストに必要な実装だけを追加
- 04テストをまとめて先に書く方法を避ける
- 05全テスト通過後にリファクタリング
活用シーン
- 01ユーザーの振る舞いに沿って機能テストを段階的に作成
- 02テストが実装詳細に依存していないか確認
- 03設計境界が未確定なら実装を保留
- 04テスト通過後にコード整理へ引き継ぐ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ carlitose/ agent-skills --skill tddインストール後、Claude Code で/tddを入力して読み込まれたか確認します。
同梱ファイルmocking.mdtests.md
詳細
テスト駆動開発
基本理念
基本原則:テストでは実装の詳細ではなく、公開インターフェイスを通じて振る舞いを検証します。コードは全面的に変更されてもかまいませんが、テストは変えるべきではありません。
良いテストは、統合テスト形式で、公開 API を通じて実際のコードパスを実行します。システムが「どのように」動作するかではなく、「何を」するかを記述します。良いテストは仕様のように読めます。「有効なカートでユーザーが決済できる」とあれば、どのような機能があるのかが正確にわかります。内部構造を気にしないため、こうしたテストはリファクタリング後も維持できます。
悪いテストは実装と強く結び付いています。内部の協調要素をモックしたり、プライベートメソッドをテストしたり、(インターフェイスを使わずにデータベースへ直接クエリするなど)外部の手段で検証したりします。警告サインは、振る舞いが変わっていないのにリファクタリングでテストが壊れることです。内部関数の名前を変更してテストが失敗するなら、そのテストは振る舞いではなく実装をテストしていたということです。
例については tests.md を、モックのガイドラインについては mocking.md を参照してください。
アンチパターン:水平スライス
テストをすべて先に書き、その後で実装をすべて書くのはやめてください。 これは「水平スライス」です。RED を「テストをすべて書くこと」、GREEN を「コードをすべて書くこと」と捉えるやり方です。
その結果、質の悪いテストが生まれます。
- テストをまとめて書くと、実際の 振る舞いではなく、想像上の 振る舞いをテストしてしまいます
- ユーザーに見える振る舞いではなく、物事の 形(データ構造や関数シグネチャなど)をテストするようになります
- 実際の変更に対するテストの感度が失われ、振る舞いが壊れても合格し、問題がなくても失敗するようになります
- 見通しを失い、実装を理解する前にテスト構造を決めてしまいます
正しいアプローチ:トレーサーバレットによる垂直スライスです。テストを1つ書き、実装を1つ行い、これを繰り返します。それぞれのテストは、前のサイクルで得た知見を反映します。コードを書いた直後なので、重要な振る舞いとその検証方法を正確に把握できます。
WRONG (horizontal):
RED: test1, test2, test3, test4, test5
GREEN: impl1, impl2, impl3, impl4, impl5
RIGHT (vertical):
RED→GREEN: test1→impl1
RED→GREEN: test2→impl2
RED→GREEN: test3→impl3
...
ワークフロー
1. 計画
コードを書く前に、以下を行います。
- 必要なインターフェイスの変更をユーザーに確認する
- テストする振る舞いをユーザーに確認する(優先順位を付ける)
- codebase-design とその 詳細化ガイダンス を使って、モジュール、インターフェイス、シームに名前を付ける
- 承認済みの設計を再利用するか、モックを作成する前にシームについて合意する
- テストする振る舞いを列挙する(実装手順ではなく)
- 計画についてユーザーの承認を得る
次のように尋ねます。「公開インターフェイスはどのような形にすべきですか? テストするうえで最も重要な振る舞いは何ですか?」
すべてをテストすることはできません。 どの振る舞いが最も重要なのかを、必ずユーザーに確認してください。考えられるすべてのエッジケースではなく、重要なパスや複雑なロジックにテストの労力を集中させます。
シームの配置が実質的に未解決で、妥当な選択によって公開 インターフェイスやテスト境界が変わる場合は、明示的な人間による確認を求め、 モック作成や実装の前に作業を停止します。シームがすでに明確、または 合意済みの場合、形式だけの確認手順を追加してはいけません。
2. トレーサーバレット
システムについて1つのことを確認するテストを1つ書きます。
RED: Write test for first behavior → test fails
GREEN: Write minimal code to pass → test passes
これがトレーサーバレットです。パスがエンドツーエンドで機能することを証明します。
3. 段階的なループ
残りの振る舞いについて、次の手順を繰り返します。
RED: Write next test → fails
GREEN: Minimal code to pass → passes
ルール:
- 一度にテストを1つだけ行う
- 現在のテストに合格するために必要なコードだけを書く
- 将来のテストを先取りしない
- テストを、観察可能な振る舞いに絞る
4. リファクタリング
すべてのテストに合格したら、焦点を絞った整理を code-simplification に依頼し、その後、凍結した 候補を code-review に渡します。TDD はどちらの品質工程も担わず、そのチェックリストを重複して作成することもありません。RED の間は決してリファクタリングしないでください。 まず GREEN に到達します。
サイクルごとのチェックリスト
[ ] Test describes behavior, not implementation
[ ] Test uses public interface only
[ ] Test would survive internal refactor
[ ] Code is minimal for this test
[ ] No speculative features added