テスト駆動開発 は何をしますか?
出力言語
デフォルトでは簡体字中国語を使用してユーザーとコミュニケーションし、テスト戦略、テスト説明、実装サマリーも簡体字中国語で記述します。ユーザーが明示的に他の言語を指定した場合、または既存のドキュメント言語で別の取り決めがある場合は、その取り決めに従います。コード、コマンド、製品名、および原文を維持する必要がある引用は強制的に翻訳しません。
哲学
中核原理: テストは公開インターフェースを通じて振る舞いを検証すべきであり、実装の詳細を検証すべきではありません。コードは完全に変更される可能性があります。テストは変更されるべきではありません。
良いテストは統合スタイルです。実際のコードパスを公開APIを通じて実行します。システムが何を行うかを記述し、どのように行うかを記述しません。良いテストは仕様のように読めます。「ユーザーは有効なカートでチェックアウトできる」は、どのような機能が存在するかを正確に示します。これらのテストは内部構造を気にしないため、リファクタリングに耐えます。
悪いテストは実装に結合しています。内部の協力者をモックし、プライベートメソッドをテストし、外部手段(データベースに直接クエリを実行するなど)で検証します。警告サイン:リファクタリング時にテストが壊れるが、振る舞いは変わっていない場合。内部関数の名前を変更しただけでテストが失敗する場合、そのテストは実装をテストしており、振る舞いをテストしていません。
例についてはtests.md、モッキングガイドラインについてはmocking.mdを参照してください。
アンチパターン: 水平スライシング
すべてのテストを先に書き、その後すべての実装を書かないでください。 これは「水平スライシング」であり、REDを「すべてのテストを書く」、GREENを「すべてのコードを書く」と見なすことです。
これは質の悪いテストを生み出します:
- 一括で書かれたテストは実際の振る舞いではなく、想像上の振る舞いをテストします
- 結局、ユーザー向けの振る舞いではなく、ものの形状(データ構造、関数シグネチャ)をテストすることになります
- テストは実際の変更に鈍感になります。振る舞いが壊れてもテストはパスし、振る舞いが正常でもテストは失敗します
- 実装を理解する前にテスト構造にコミットしてしまい、先走りになります
正しいアプローチ: トレーサー弾による垂直スライス。1テスト→1実装→繰り返し。各テストは前のサイクルから学んだことに応答します。コードを書いたばかりなので、どの振る舞いが重要で、どのように検証すべきかを正確に理解しています。
間違い(水平):
RED: test1, test2, test3, test4, test5
GREEN: impl1, impl2, impl3, impl4, impl5
正しい(垂直):
RED→GREEN: test1→impl1
RED→GREEN: test2→impl2
RED→GREEN: test3→impl3
...
ワークフロー
1. 計画
コードベースを探索する際は、CONTEXT.md(存在する場合)を読み、テスト名とインターフェース語彙がプロジェクトのドメイン言語に一致するようにし、対象領域のADRを尊重します。
コードを書く前に:
- ユーザーと必要なインターフェース変更について確認する
- ユーザーとテストすべき振る舞い(優先順位付け)について確認する
- インターフェース境界が不明確な場合、コードベース設計原則を使用して深いモジュールの機会を特定する。ユーザーが明示的に要求しない限り、別のスキルを自動的に呼び出さない。
- テストすべき振る舞い(実装手順ではない)をリストアップする
- 計画についてユーザーの承認を得る
質問例: 「公開インターフェースはどのようなものにすべきですか? どの振る舞いが最も重要ですか?」
すべてをテストすることはできません。 どの振る舞いが最も重要かをユーザーと正確に確認してください。重要なパスと複雑なロジックにテストの労力を集中させ、すべての可能なエッジケースには注力しないでください。
2. トレーサー弾
システムに関する1つのことを確認する1つのテストを書きます:
RED: 最初の振る舞いのテストを書く → テストが失敗
GREEN: テストをパスする最小限のコードを書く → テストがパス
これがトレーサー弾です — パスがエンドツーエンドで機能することを証明します。
3. インクリメンタルループ
残りの各振る舞いについて:
RED: 次のテストを書く → 失敗
GREEN: パスする最小限のコード → パス
ルール:
- 一度に1つのテスト
- 現在のテストをパスするのに十分なコードだけ
- 将来のテストを予測しない
- テストは観察可能な振る舞いに焦点を当てる
4. リファクタリング
すべてのテストがパスした後、リファクタリング候補を探します:
- 重複を抽出する
- モジュールを深くする(複雑さをシンプルなインターフェースの背後に移動)
- 自然な場所でSOLID原則を適用する
- 新しいコードが既存コードについて何を明らかにするかを検討する
- 各リファクタリングステップの後にテストを実行する
REDの状態ではリファクタリングしないでください。 まずGREENにしてください。
サイクルごとのチェックリスト
[ ] テストは振る舞いを記述しており、実装を記述していない
[ ] テストは公開インターフェースのみを使用している
[ ] テストは内部リファクタリングに耐えられる
[ ] コードはこのテストに対して最小限である
[ ] 推測的な機能は追加されていない