tdd について
既存のコードベースで作業するエージェント向けの開発スキルです。小さなレッド・グリーン・リファクタリングの反復で実装し、テストの選定や検証、阻害要因の報告を行います。
主な機能
- 01小さなレッド・グリーン・リファクタリングの反復
- 02テスト要否の判断基準
- 03テスト対象のインターフェースと協力要素の選定
- 04テスト期待値を正しく保つルール
- 05検証と完了報告
活用シーン
- 01新しい動作の回帰テスト作成
- 02報告された不具合の修正前の再現
- 03テスト先行が難しい変更の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ marcellocurto/ skills --skill tddインストール後、Claude Code で/tddを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yamltest-evidence.md
詳細
テスト駆動開発
小さなレッド → グリーン → リファクタリングのサイクルで進めます。1つの振る舞いをテストとして書き、失敗することを確認してから実装し、変更したコードを整えます。プロジェクトに用語集や関連する ADR がある場合は、ファイル名にかかわらず目を通し、テストでプロジェクトのドメイン用語を使います。
テストが必要かどうかを判断する
今後ユーザーや呼び出し元が頼りにするルールを追加または変更する場合にのみ、テストを書きます。テストは、そのようなルールに対する現実的な回帰を検出するためのものです。カバレッジを上げること自体は、テストを書く理由にはなりません。そのようなルールが生まれない変更であれば、その旨を1行で述べ、サイクルを行わずに実装します。
テストではシステムが何をするかを記述します。機能、ルート、オプション、デフォルトが存在しないことを断言するテストは書かないでください。拒否やデフォルトが仕様として約束されているなら、それは振る舞いです。エンドポイントが認証情報なしで 401 を返す、または破壊的なフラグがオフの状態で始まる、といった結果そのものをテストします。振る舞いを削除する場合は、それを対象としていたテストを削除し、残っている呼び出し元を探して、残りのテストスイートを実行します。テストスイートが対象にするのは、すでにテストしていた範囲だけなので、残りの呼び出し元を直接確認してください。
設計、UI、アイデアの草案を作成している間は、テストを書かないでください。振る舞いについて合意し、実装に取りかかる段階でテストを書きます。
テストを選ぶ
テストを書く前に、期待する結果を定める要件、開始条件、そしてテストで検出すべき現実的な失敗を明確にします。
- その振る舞いを担うインターフェースを通してテストします。公開 API の場合もあれば、内部モジュールのインターフェースの場合もあります。既存のインターフェースと、コードの近くにあるテストの慣例を優先します。
- テストで主張する内容に実際の協力要素の振る舞いが関わる場合は、実際の協力要素を使います。依存関係を置き換えるのは、時間、乱数、失敗を制御する場合、またはその依存関係がテストの対象範囲外にある場合に限ります。test-evidence.md には、一般的な契約の証拠として何が認められるか、テストダブルが適切なのはどのような場合かが記載されています。
- 重要な経路や複雑なロジックをカバーします。あらゆるエッジケースをカバーしようとしないでください。
- テストを書きやすくするだけの目的で、非公開の状態を公開したり、公開メソッド、ラッパー、設定を追加したりしないでください。インターフェース自体が問題となっている場合は、
codebase-designスキルを使用します。
サイクル
機能追加とバグ修正には、同じサイクルを適用します。バグの場合、最初のテストでは、失敗する振る舞いを担う最も限定的なインターフェースを通して報告された失敗を再現します。その際、コードの近くにあるテストの慣例に従います。
- 観測できる最小の振る舞いを選びます。
- その振る舞いに絞ったテストを1つ書きます。
- 本番コードを変更する前にテストを実行し、振る舞いが欠けているために失敗することを確認します。セットアップやテストの誤りで失敗する場合は、まずテストを修正します。テストが通る場合は、振る舞いがすでに存在するか確認します。存在するなら、本番コードを変更せず、その旨を報告します。テストが振る舞いを捉えられていない場合は、テストを修正します。
- テストに通る、最もシンプルで本番品質の変更を加えます。後続のテストのための振る舞いは追加しないでください。
- テストを実行し、通ることを確認します。
- 所有責任や凝集性が損なわれている場合は、変更したコードをリファクタリングし、テストを再実行します。
- 得られた知見をもとに、次の振る舞いを選びます。テストを最初にすべて書かないでください。
再現性のないバグの場合は、回帰テストを決定的なものにし、そのテストで何を固定するのかを述べます。バグがより広い種類の失敗の一部である場合は、まず報告されたケースを修正し、その後、類似するケースも検討します。
期待する結果を正直に保つ
要件が変更された場合、要件に照らしてテストが誤っていた場合、または保護対象の動作を維持したままインターフェースが変更された場合に限り、テストの期待結果を変更してください。変更する場合は、その理由を説明してください。実装の新しい出力は、期待結果を変更する理由にはなりません。
こうした対応は、動作を修正せずにテストを成功させるものです。次の対応はしないでください。
- 新しい出力に合うようにアサーション、スナップショット、フィクスチャを更新する
- フラグ、バックフィル、初期化済みデータなど、実際のワークフローでは保証されない状態をセットアップでシードする
- テスト対象と称するロジックや連携をモックで無効化する
- エラーを成功として受け入れる、または要件が正常に動作する経路を求めているのに、正常な拒否だけをテストする
- テストをスキップする、想定される失敗としてマークする、または実行対象から除外する
- 本番コードと同じロジックで期待値を計算する
正当な失敗テストの解決に、ドメイン上の判断、不足している前提条件、または合意した範囲外の作業が必要な場合は、テストを失敗したままにし、完了した作業は維持したうえで、妨げとなっている事項と作業が未完了であることを報告してください。バグの再現だけを求める依頼は、テストが失敗したままでも完了であり、本番コードの修正を許可するものではありません。
失敗するテストの実施が現実的でない場合
サイクルに従うためだけに、大規模なテスト基盤、時間のかかるエンドツーエンドのセットアップ、または複雑なモックを構築しないでください。実装する前に制約を説明し、動作が欠落していることと修正されたことを示せる別の確認方法を選んでください。たとえば、スクリプト、コマンド、ブラウザのワークフロー、ログの確認などです。何も実行できない場合は、その不足を報告してください。
実装後に作成したテストも回帰防止には役立ちますが、テストファーストで作業した証拠にはなりません。古いコードに対して実行し、失敗したはずであることを示した場合は、そのように明記してください。
検証
各サイクルで、対象を絞ったテストと変更箇所に近いテストを実行してください。共有契約やリポジトリのルールで必要な場合は、より広範なチェックも実行し、最後にリポジトリで必須のチェックを一度実行してください。根拠としているテストが実際に実行されたことを確認してください。テストがスキップされたために成功したコマンドは、何の証拠にもなりません。
最終回答
- 変更前に失敗したテストまたはチェックと、その失敗内容。あるいは、テストが不要だった理由を一行で記載
- 変更後に成功した実行結果。または、依然として失敗しているテストとその妨げとなっている事項
- 実行したその他のチェックと、その結果
- 変更前の失敗を示す証拠を得られなかった場合は、その理由と代わりに使用したチェック