tdd について
開発者やコーディングエージェント向けの TDD スキルです。公開インターフェースで動作を検証し、テスト境界とリポジトリ固有のコマンドを確認してから、段階的なレッド・グリーンサイクルを進めます。
主な機能
- 01公開インターフェースでの動作テスト
- 02段階的なレッド・グリーン反復
- 03リポジトリ固有のテスト手順確認
- 04テスト境界と計画の合意
- 05グリーン後のリファクタリング
活用シーン
- 01観察可能な動作に沿ったテスト計画
- 02動作を一つずつ実装
- 03内部実装に依存するテストの回避
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ helderberto/ agent-skills --skill tddインストール後、Claude Code で/tddを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/mocking.mdtests.mdui-tests.md詳細
テスト駆動開発
基本理念
基本原則:テストでは、実装の詳細ではなく、公開インターフェースを通じて動作を検証します。コードは全面的に変更されることがありますが、テストはそうあるべきではありません。
良いテストは、統合テストのように実際のコードパスを公開 API 経由で実行します。システムが「どのように」動作するかではなく、「何を」するかを記述します。良いテストは仕様のように読めます。「有効なカートでユーザーがチェックアウトできる」とあれば、どの機能があるのかが正確にわかります。内部構造を気にしないため、こうしたテストはリファクタリング後も有効です。
悪いテストは実装と密結合しています。内部の協調オブジェクトをモックしたり、プライベートメソッドをテストしたり、外部の手段(インターフェースを使わずにデータベースを直接クエリするなど)で検証したりします。警告サインは、動作に変更がないのにリファクタリングでテストが失敗することです。内部関数の名前を変更してテストが失敗するなら、そのテストが検証していたのは動作ではなく実装です。
例はtests.md、モックのガイドラインはmocking.md、ユーザーフローのエンドツーエンドテストはui-tests.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
...
アンチパターン:同語反復的なテスト
アサーションが、コードと同じ方法で期待値を再計算しています。たとえば、expect(add(a, b)).toBe(a + b)、同じロジックで手作業から導いたスナップショット、あるいは定数をそれ自身と等しいと検証するケースです。テストは構造上必ず成功するため、コードと食い違うことはありません。
期待値は、独立した信頼できる情報源に基づいている必要があります。正しいとわかっているリテラル、計算例、仕様などを使用してください。例はtests.mdを参照してください。
ワークフロー
0. 技術スタックを確認する
TDD サイクルは普遍的ですが、コマンドはそうではありません。最初のテストの前に、このリポジトリでのテスト方法を確認し、RED と GREEN の各段階でそのコマンドを使用してください。
- ビルドシステム:
package.json、pyproject.toml、go.mod、Cargo.toml、Makefile - まずリポジトリに含まれるラッパーを使います:
./gradlew、./mvnw、make test、リポジトリのスクリプトなど。リポジトリで使われていない、グローバルにインストールされたツールは決して使わないでください - 単一のテストに絞ったコマンドと、全テストスイートを実行するコマンドを確認します。ループ中は絞り込んだテストを実行し、完了前に一度だけ全テストスイートを実行します
- テストの配置場所、命名規則、近隣のテストで使われているパターンを確認します
- CI ワークフローで、マージの可否を実際に判定するコマンドを確認します
npm testを前提にしないでください。
1. 計画
コードベースを調査するときは、テスト名やインターフェースの用語がプロジェクトのドメイン用語に合うように、GLOSSARY.md があればそれを(なければ従来の CONTEXT.md を。複数のコンテキストがあるリポジトリでは GLOSSARY-MAP.md が適切なファイルを示します)読み、作業対象の領域に関する ADR を遵守してください。
シームとは、テスト対象となる公開境界です。内部に立ち入らずに動作を観察するインターフェースを指します。テストを書く前に、テスト対象のシームをそれぞれ1行で書き出し、そのシームでテストできることとできないことを記載して、ユーザーに確認してください。
次のように尋ねます。「公開インターフェースは何ですか? どのシームをテストするべきですか?」
確認されていないシームでは、テストを書きません。
コードを書く前に、次のことを行います。
- テスト対象のシームをユーザーに確認する
- テストする動作の優先順位をユーザーと確認する
- ディープモジュール(小さなインターフェース、深い実装)の機会を特定する。用語とテスト可能性の確認には
codebase-designを指定して Skill ツールを呼び出します - テストする動作を(実装手順ではなく)列挙する
- 計画についてユーザーの承認を得る
すべてをテストすることはできません。 あらかじめシームについて合意することで、あらゆるエッジケースではなく、重要な経路や複雑なロジックにテストの労力を注げます。
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. リファクタリング
GREEN になってからのみ行い、RED の間は決して行いません。重複を抽出し、モジュールを深め(用語については codebase-design を指定して Skill ツールを呼び出します)、新しいコードから既存のコードについて何が分かるかを確認します。各ステップの後にテストを実行します。