tdd について
tddは、コーディングエージェント向けのテスト駆動開発スキルです。実装前に失敗するテストを確認し、合意したテスト境界と要件IDに沿って段階的な実装を進めます。
主な機能
- 01実装前に失敗するテストを作成
- 02段階的なレッド・グリーン・リファクタリング
- 03実装前に想定どおりの失敗を確認
- 04合意した公開境界でテスト
- 05テストに要件IDを付与
- 06モックと完了条件を確認
活用シーン
- 01新しい振る舞いのテストファースト開発
- 02修正前に不具合をテストで再現
- 03要件とテスト境界に沿ったカバレッジ管理
- 04変更完了前の検証条件の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jayden-dang/ skills --skill tddインストール後、Claude Code で/tddを入力して読み込まれたか確認します。
詳細
TDD
鉄の掟
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
テストより先に実装を書きましたか? それを削除してください。「参考として残す」のでも、「テストが追いつくまで調整する」のでもありません。そうすると、要求された内容ではなく、自分が作ったものをテストすることになります。削除とは削除することです。テストからやり直してください。この掟の文言に反することは、その精神に反することでもあります。
例外が認められるのは、ユーザーから明示的な許可を得た場合に限ります。一時的なプロトタイプ、生成コード、純粋な設定が該当します。「今回だけ省略する」は例外ではありません。このスキルが阻止しようとしている、もっともらしい言い訳です。
テストを置く場所:事前に合意したシーム
シームとは、内部に立ち入らずに動作を観測できる公開サーフェスです。テストは、機能の design.md の テスト対象のシーム に記載されたシームでのみ実施します。その表で確認できないシームに対するテストは拒否してください。この作業に design.md がない場合(ティア 0/1 の変更、またはレガシー領域)は、最初のテストを書く前にシームを提案し、ユーザーの合意を得てください。テストにかける労力は予算です。合意したシームを使えば、あらゆる内部詳細ではなく、クリティカルパスに労力を集中できます。
ループ
一度に 1 つの垂直スライスに取り組みます。1 つの動作 → 1 つのテスト → 最小限の実装 → 繰り返し。各サイクルは、前のサイクルから得た学びを踏まえて進めます。テストをすべて先に書き、その後ですべてのコードを書くことは決してしないでください。まとめて書いたテストは、想像上の動作を検証することになります。
RED — 失敗するテストを 1 つ書きます。 1 つの動作、動作を示す名前、合意したシームにおける実コードへの期待を設定します。検証する要件 ID を付けます(以下を参照)。バグを修正する場合は、必須のサブスキルとして、まず debug を使って根本原因を特定してください。RED テストは、そのバグを再現し、修正前にそのバグが原因で失敗しなければなりません。
RED を確認 — 必須、省略不可。 テストを実行します(docs/agents/project.md に記載された単一ファイル用コマンドを使用)。失敗すること、想定したエラーメッセージが表示されること、そしてタイプミスやインポートエラーではなく、動作が欠けているために失敗することを確認します。テストがすぐに通りましたか? すでに存在する動作をテストしています。コードではなくテストを修正してください。失敗ではなくエラーになりましたか? 正しく失敗するまでエラーを修正し、再実行してください。
GREEN — 通過する最もシンプルなコードを書きます。 推測によるパラメーターや追加機能を加えたり、無関係なコードに触れたりしないでください。
GREEN を確認 — 必須。 全テストスイートを実行します。新しいテストが通ること、ほかのすべてのテストも引き続き通ること、出力に問題がないことを確認します。警告が 0 件、不要なエラーが 0 件で、「あとで整理する」ものが何もない状態にしてください。新しいテストが失敗しましたか? テストを緩めず、コードを修正してください。ほかのテストが失敗しましたか? ほかの作業に進む前に、今すぐ修正してください。
REFACTOR — 通過している間だけ行います。 重複を削除し、名前を改善し、ヘルパーを抽出します。変更のたびにテストスイートを再実行してください。動作は追加しないでください。
次のスライスに進みます。
要件のタグ付け
すべてのテストに、検証対象の要件 ID を付けます。docs/agents/project.md の規約(テスト注釈規約の表)に従ってください。一般的な形式は次のとおりです。
| レイヤー | 規約 |
|---|---|
| E2E(例:Playwright) | { tag: ['@CODE-N.M'] } |
| 単体テスト(例:Vitest) | annotate('CODE-N.M', 'requirement')、またはテスト名に ID を含める |
| コンパイル言語(例:Rust) | テストの上に /// REQ: CODE-N.M というドキュメントコメントを記述 |
その動作を対象とする要件がありませんか? ティア ≥1 の作業では、それはギャップです。追跡できないテストをリリースせず、ユーザーに伝えてください。docs/agents/project.md が見つからない場合は、その旨を伝え、setup-repo の実行を提案し、テスト名に ID を入れる方法で進めてください。
アンチパターンとその対策
| アンチパターン | 見分け方 | 対策 |
|---|---|---|
| 同語反復的なテスト | コードと同じ方法で期待値を再計算している(expect(sum(items)).toBe(items.reduce(...)))ため、必ず成功する | 既知の正しいリテラル、具体的な計算例、要件の記述など、独立した正解の情報源から期待値を取得する |
| 実装に依存したテスト | 振る舞いを変えずにリファクタリングしただけで失敗する。呼び出し回数や順序、プライベートメソッドを検証したり、インターフェースではなくサイドチャネル(生の DB クエリなど)を使って検証したりする | 公開された境界を通じて、観測可能な振る舞いだけを検証する |
| モックの振る舞いをテストする | モックが存在することや呼び出されたことを検証している。モックを削除するとテストが失敗する | 実際のコンポーネントをテストするか、モックに対する検証を完全にやめる |
| 本番クラスにテスト専用のメソッドを追加する | テストファイルからしか呼ばれないメソッド(例:destroy())がある | テストユーティリティに移す。本番クラスには本番用の API だけを持たせる |
| 不完全なモック | テストがたまたま読み取るフィールドだけをモックに持たせている。省略されたフィールドが原因で統合時に問題が起きる | 実際のデータ構造全体を再現する。実際のレスポンスに含まれるすべてのフィールドを含める |
| 自分たちのモジュールをモックする | 「分離するため」に内部の協調オブジェクトをスタブ化している | システム境界(外部 API、時刻、乱数、ときには FS/DB)でのみモックを使う。自分たちが所有するコードは決してモックしない。それが必要に思えるなら、設計の結合度が高すぎるため、依存関係を注入する |
モックのセットアップがテストロジックより長い場合や、モックを削除するとテストが失敗する場合は、モックに問題があります。実際のコンポーネントを通じた統合テストを優先してください。
よくある言い訳
| 考え | 実際のところ |
|---|---|
| 「テストするほど複雑ではない」 | 単純なコードも壊れます。テストにかかるのは 1 分です |
| 「すぐ後でテストを追加する」 | 後から書いたテストはすぐ成功し、何も証明しません。テストが何かを検出するところを見たことがないからです |
| 「テストを後から書いても、目的は同じ」 | テストを後から書くと「これは何をするのか?」に答え、テストを先に書くと「これは何をすべきか?」に答えます。前者は自分の実装に偏ります |
| 「手動で一度動かして確認した」 | その場限りで記録もなく、再現もできません。次の変更で消えてしまいます |
| 「何時間もかけた作業を消すのはもったいない」 | サンクコストです。テストされていないコードを残すことこそ、実際の無駄です |
| 「テストを書く間、参考として残しておく」 | 手順を増やしてテストを後から書いているだけです |
| 「テストを書くのが難しい」 | テストしにくいものは使いにくいものです。テストを省略せず、インターフェースを簡素化してください |
| 「TDD は作業を遅くする」 | タイピングよりは遅いですが、デバッグよりは速いです |
| 「このファイルには、そもそもテストがない」 | 変更を加えるのはあなたです。その変更にはテストを追加してください |
危険信号 — 作業を中断してやり直す
- 実装が存在するのに、そのテストが存在しない
- 新しいテストが初回実行で成功した
- RED でテストが失敗した理由を説明できない
- テストが、設計の境界テーブルにない境界を対象としている
- テストに要件 ID がない
- 「今回だけ」「参考として残す」「形式ではなく精神」「このケースは違う」
どれか一つでも当てはまる場合は、テストされていないコードを削除し、RED に戻ってください。
完了を宣言する前に
- 新しい振る舞いにはすべて、想定した理由で最初に失敗するのを確認したテストがある。エラー経路や境界値も振る舞いに含まれる
- テストスイート全体が成功し、出力に警告やエラーが一切ない
-
docs/agents/project.mdに従って、すべてのテストに要件 ID が付いている - すべてのテストが、
design.md(またはユーザー)と合意した境界で行われている - モックはシステム境界でのみ使われ、完全なデータ構造を備え、モックに対する検証がない
チェックできない項目がありますか?作業はまだ完了していません。必須のサブスキル:完了を宣言する前に verify を使用してください。