tdd について
tddは、コーディングエージェント向けにテスト駆動開発を導くスキルです。パブリックインターフェースを通じて観察可能な振る舞いを検証し、テストと実装を一つずつ交互に進めます。
主な機能
- 01パブリックインターフェース経由の動作検証
- 02テストと実装を一つずつ交互に実施
- 03観察可能な振る舞いに焦点を当てたテスト
- 04作成前のテスト価値の確認
- 05テスト合格後のリファクタリング
活用シーン
- 01新機能の振る舞いテストを段階的に追加
- 02バグ修正の回帰を検証
- 03既存テストのレビューや整理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ bastani-inc/ atomic --skill tddインストール後、Claude Code で/tddを入力して読み込まれたか確認します。
詳細
テスト駆動開発
フィロソフィー
基本原則:テストでは、実装の詳細ではなく公開インターフェースを通じて振る舞いを検証します。コードは全面的に変更されてもかまいませんが、テストは変わるべきではありません。
良いテストは、統合テスト形式です。公開 API を通じて実際のコードパスを実行します。システムが「どのように」動作するかではなく、「何を」するかを記述します。良いテストは仕様書のように読めます。「ユーザーは有効なカートでチェックアウトできる」とあれば、どのような機能があるのかが正確にわかります。内部構造を気にしないため、リファクタリング後も通用します。
悪いテストは実装と密結合しています。内部の協調オブジェクトをモックしたり、非公開メソッドをテストしたり、外部の手段(インターフェースを使わずデータベースに直接クエリを送るなど)で検証したりします。警告サインは、振る舞いが変わっていないのにリファクタリングでテストが壊れることです。内部関数の名前を変更しただけでテストが失敗するなら、そのテストは振る舞いではなく実装をテストしていました。
例については tests.md、モックのガイドラインについては mocking.md、新しいテストが必ず通過しなければならない価値のゲートと、既存テストを監査するワークフローについては test-audit.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. 計画
コードベースを調査するときは、プロジェクトのドメイン用語集を使い、テスト名やインターフェースの用語をプロジェクトの言葉に合わせ、作業対象の領域に関する ADR を遵守してください。
コードを書く前に、次のことを行います。
- 必要なインターフェースの変更についてユーザーに確認する
- テストする振る舞い(優先順位を含む)についてユーザーに確認する
- ディープモジュール(小さなインターフェースと深い実装)の機会を特定する
- テスト容易性を考慮してインターフェースを設計する
- 実装手順ではなく、テストする振る舞いを列挙する
- 計画についてユーザーの承認を得る
次のように質問してください。「公開インターフェースはどのような形にすべきですか? テストするうえで最も重要な振る舞いは何ですか?」
すべてをテストすることはできません。 どの振る舞いが最も重要かを、具体的にユーザーに確認してください。考えられるすべてのエッジケースではなく、重要なパスや複雑なロジックのテストに注力します。
2. トレーサーバレット
システムに関する1つのことを確認するテストを1つ書きます。
RED: Write test for first behavior → test fails
GREEN: Write minimal code to pass → test passes
これがトレーサーバレットです。パスがエンドツーエンドで機能することを確認します。
各テストを書く前に、作成ゲートを通してください。そのテストが保護する振る舞い、それを壊す回帰、既存のテストカバレッジではすでに検出できない理由、ほかでは使わない本番コードの接続点が必要かどうかを明確にします。バグ修正の場合、最初の RED テストは、修正前のコードで、バグの説明にある理由によって失敗しなければなりません。
3. 段階的なループ
残りの各振る舞いについて、次の手順を繰り返します。
RED: Write next test → fails
GREEN: Minimal code to pass → passes
ルール:
- 一度にテストは1つ
- 現在のテストを通すために必要な最小限のコードだけを書く
- 先のテストを予測しない
- テストは観測可能な振る舞いに絞る
4. リファクタリング
すべてのテストがパスしたら、リファクタリング候補を探します。
- 重複を抽出する
- モジュールを深化させる(複雑さをシンプルなインターフェースの背後に移す)
- 自然な場合は SOLID 原則を適用する
- 新しいコードから既存のコードについて何が分かるかを検討する
- リファクタリングの各ステップの後にテストを実行する
RED の状態でリファクタリングしてはいけません。 まず GREEN にします。
既存テストの監査
テストの作成ではなく、テストのレビューや整理を依頼された場合は、監査ワークフローに従います。まずテスト、そのテストが対象とする本番コード、およびその履歴を読みます。読み取り専用で確認し、候補ごとに根拠を記録します。まとまりのある単位で編集し、保持基準を満たすテストは残します。
サイクルごとのチェックリスト
[ ] Test passes the authoring gate (behavior, regression, not already covered, no test-only seam)
[ ] Test describes behavior, not implementation
[ ] Test uses public interface only
[ ] Test would survive internal refactor
[ ] Bug fixes only: the regression test failed on the pre-fix code for the intended reason
[ ] Code is minimal for this test
[ ] No speculative features added