tdd について
tdd は、言語やテストランナーを問わず TDD を進めるエージェントスキルです。安定した境界での振る舞い検証と、1件ずつの RED–GREEN サイクルを重視し、コード変更前に仕様上の判断事項を確認します。
主な機能
- 01安定した境界で振る舞いをテスト
- 021件ずつ RED–GREEN サイクルを実施
- 03プロジェクトの言語とテスト慣習に適応
- 04編集前に仕様上の契約を確認
- 05失敗ケースと境界条件を網羅
活用シーン
- 01機能を段階的に開発
- 02報告された不具合を再現して修正
- 03実装詳細に依存するテストを回避
- 04回帰と既存のテスト失敗を区別
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hburaktasyurek/ agent-skills-and-commands --skill tddインストール後、Claude Code で/tddを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
deep-modules.mdinterface-design.mdmocking.mdrefactoring.mdtests.mdagents/openai.yaml詳細
テスト駆動開発
哲学
基本原則:テストでは、利用可能な最も安定した契約境界を通じて観測可能な振る舞いを検証し、偶発的な実装の詳細は検証しないでください。コードは全面的に変更されてもかまいませんが、振る舞いが変わらない限り、テストは失敗すべきではありません。
優れたテストは、統合テストのように実際のコードパスをパブリック API 経由で実行します。システムが「どのように」動作するかではなく、「何を」するかを記述します。優れたテストは仕様のように読めます。「ユーザーは有効なカートでチェックアウトできる」とあれば、どのような機能があるのかが明確です。内部構造を気にしないため、リファクタリング後もテストはそのまま機能します。
悪いテストは実装に密結合しています。内部の協調コンポーネントをモックしたり、プライベートメソッドをテストしたり、偶発的な呼び出し順序をアサートしたりします。注意すべき兆候は、振る舞いを保ったまま内部の名前を変更したり並べ替えたりしたときにテストが失敗することです。
パブリックなレスポンスだけでは、十分な証拠にならないことがあります。永続化、冪等性、並行性、キュー、復旧の契約を検証するには、新しいプロセス、独立した接続、コミット後の読み取り、または永続状態のアサーションが必要になる場合があります。それが観測可能な契約の一部であれば、その証拠を使ってください。成功レスポンスやモックとのやり取りを、実際の不変条件の代わりにしてはいけません。
例については tests.md、モックのガイドラインについては mocking.md を参照してください。
言語とツール
ここでの原則、つまり実装より振る舞いを重視すること、システム境界でのみモックすること、ディープモジュールを使うことは、言語に依存しません。例では説明のために TypeScript/Jest を使っています。**テストを書く前に、プロジェクトの言語、テストランナー、アサーションのスタイル、モックの規約を確認し、それらに従ってください。**構文ではなく原則を適用してください。Python プロジェクトでは pytest のイディオムとフィクスチャを使い、PHP プロジェクトでは PHPUnit の規約を使い、JS/TS プロジェクトでは既に使用されているランナー(Jest/Vitest/node:test)を使います。プロジェクトで採用されていないイディオムを持ち込まないでください。
アンチパターン:水平スライス
**すべてのテストを先に書き、その後ですべての実装を書くのはやめてください。**これは「水平スライス」です。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
...
契約ゲート
編集する前に、リポジトリの指示と、正式なタスク、概要、仕様、またはレビューの指摘を読みます。契約の準備が整っているか判断するために、実装とテストを十分に確認します。
- 振る舞い、範囲、パブリックインターフェース、受け入れ条件、決定権がすでに確定している場合は、それを承認と見なし、最初の RED サイクルを開始します。ユーザーに計画の再確認を求めたり、成果物にすでに記載されている決定を繰り返し確認したりしないでください。
- 製品の振る舞いや範囲を変えない技術的な詳細は、リポジトリ内の証拠をもとに解決します。
- 成果物同士に矛盾がある場合、または重要な振る舞い、範囲、インターフェース、優先度、決定権に関する判断が残っている場合は、リポジトリに変更を加えないでください。証拠の矛盾を報告し、作業を妨げている点について具体的な質問を1つ尋ねます。
- 直接の依頼が正式かつ完結している場合、チケット、ロードマップ、個別のテスト計画といった手続きの欠如を、作業の妨げにしないでください。
因果関係を閉じるために必要な振る舞いを、失敗モードと境界条件も含めて、最小限の順序付きリストにします。これは実行の指針として扱い、契約ゲートで本当に人間の判断が必要と確認された場合を除き、承認待ちで作業を止めないでください。
ワークフロー
1. 最初の RED
機能の場合は、承認済みの契約に沿った、エンドツーエンドの動作として最も小さなものを選びます。バグの場合は、まず報告された失敗を、バグを証明できる境界で再現します。
焦点を絞ったテストを 1 つ書き、実行します。RED が妥当なのは、想定どおり、未実装または誤った動作が原因で失敗した場合に限ります。構文エラー、壊れたフィクスチャ、利用できない依存関係、無関係な既存の失敗は、有用な RED ではありません。テストのセットアップを修正するか、プロダクトコードを変更せずに外部要因によるブロッカーを報告します。
すべてをテストすることはできません。しかし、「重要な動作」には、正常系だけでなく、システムがどのように失敗するかも含まれます。 信頼できる契約と、リポジトリのリスクを示す証拠に基づいて優先順位を付けます。エラー処理、無効な入力、境界条件、失敗モードを、第一級の動作として扱います。契約の確認で本当に未解決の判断事項が見つかった場合に限り、ユーザーに確認します。些細な組み合わせは省略しても、異なる失敗パスは省略しません。
2. GREEN
既知の契約に違反せず、焦点を絞った動作を通す、根本原因に対処した最小限の変更を実装します。「最小限」とは、同じ原因のパスが残ったまま、報告された行だけを修正することではありません。
RED: Write test for first behavior → test fails
GREEN: Write minimal code to pass → test passes
これはトレーサーバレットです。このパスがエンドツーエンドで機能することを証明します。
続行する前に、焦点を絞ったテストを実行し、GREEN であることを確認します。
3. インクリメンタルループ
残りの動作について、次の手順を繰り返します。
RED: Write next test → fails
GREEN: Minimal code to pass → passes
ルール:
- 一度にテストは 1 つ
- 現在のテストを通すのに必要な分だけコードを書く
- 将来のテストを先回りしない
- 観測可能な動作にテストを絞る
- 前のサイクルで得た証拠をもとに、次のテストを追加する
- 完了を宣言する前に、タスクが対象とする成功、失敗、境界、および同じ根本原因に起因する回帰の範囲を網羅する
4. リファクタリング
すべてのテストが通ったら、リファクタリング候補を確認します。
- 重複を抽出する
- モジュールを深める(複雑さをシンプルなインターフェースの背後に移す)
- 自然な範囲で SOLID 原則を適用する
- 新しいコードから既存コードについて何が分かるか検討する
- リファクタリングの各ステップの後にテストを実行する
RED の間は絶対にリファクタリングしないでください。 まず GREEN にします。
焦点を絞ったサイクルがすべて GREEN になったら、関連するより広範なテストスイートを実行します。無関係な既存の失敗と、タスクによって発生した回帰を区別します。無関係な失敗を黙って修正したり、隠したりしないでください。
サイクルごとのチェックリスト
[ ] Test describes behavior, not implementation
[ ] Test uses the stable observable boundary
[ ] Test would survive internal refactor
[ ] RED failed for the expected reason
[ ] Code is minimal for this test
[ ] No speculative features added