テスト駆動開発(TDD)
TDD(テスト駆動開発)はレッド→グリーンのループです。このスキルは、そのループが価値のあるテストを生み出すためのリファレンスです。すなわち、良いテストとは何か、テストをどこに配置するか、アンチパターン、そしてループのルールを定義します。各セクションはすべてのサイクルで適用されます。ループの前と最中に参照し、後回しにしてはいけません。
コードベースを探索する際は、GLOSSARY.md(存在する場合)を読んでください。テスト名やインターフェースの語彙がプロジェクトのドメイン言語と一致するようにし、触れる領域のADR(アーキテクチャ決定記録)を尊重してください。
良いテストとは
テストは、実装の詳細ではなく、公開インターフェースを通じて振る舞いを検証します。コードが完全に変わっても、テストは変わるべきではありません。良いテストは仕様書のように読めます。「ユーザーは有効なカートでチェックアウトできる」というテストは、存在する機能を正確に示し、内部構造を気にしないため、リファクタリング後も生き残ります。
例についてはtests.mdを、モッキングのガイドラインについてはmocking.mdを参照してください。
シーム:テストを配置する場所
シームとは、テスト対象の公開境界です。内部に触れずに振る舞いを観測できるインターフェースです。テストはシームに配置し、内部に対しては決して書きません。
事前に合意したシームでのみテストを書きます。 テストを書く前に、テスト対象のシームを書き出し、ユーザーと確認してください。確認されていないシームにはテストを書きません。すべてをテストすることはできないため、シームを事前に合意することで、テストの労力をすべてのエッジケースではなく、重要なパスと複雑なロジックに集中させることができます。
質問:「公開インターフェースは何ですか?どのシームをテストすべきですか?」提案する各シームについて、それが何を捕捉し、何を見逃すかを一行でメモしてください。
インターフェースの形状自体が疑問である場合(モジュールの深さ、シームの位置、インターフェースが公開すべきもの)、Skillツールを "codebase-design" で呼び出し、語彙を確認してください。これはモジュール、インターフェース、深さ、シーム、アダプター、レバレッジ、ローカリティの用語の共有ソースであり、実行するセッションではなく、参照するリファレンスです。
アンチパターン
- 実装結合:内部の協調オブジェクトをモックする、プライベートメソッドをテストする、またはサイドチャネルを通じて検証する(インターフェースを使わずにデータベースに問い合わせる)。兆候:リファクタリング後に振る舞いが変わっていないのにテストが壊れる。
- トートロジー:アサーションがコードと同じ方法で期待値を再計算する(
expect(add(a, b)).toBe(a + b)、同じ方法で手動で導出したスナップショット、自分自身に等しいとアサートされた定数)。そのため、構成的にパスし、コードと矛盾することがない。期待値は独立した真実のソース(既知の正しいリテラル、実例、仕様)から得る必要があります。 - 水平スライシング:すべてのテストを先に書き、その後ですべての実装を書く。バルクのテストは想像上の振る舞いを検証します。つまり、ユーザーに直面する振る舞いではなく、ものの形状をテストし、テストは実際の変更に鈍感になり、実装を理解する前にテスト構造にコミットしてしまいます。代わりに垂直スライスで作業してください。1つのテスト → 1つの実装 → 繰り返し。各テストはトレーサーバレットであり、前のサイクルから学んだことに応答します。
ループのルール
- レッドの前にグリーンはない。 最初に失敗するテストを書き、その後、それをパスするのに必要な最小限のコードだけを書きます。将来のテストを予測したり、推測的な機能を追加してはいけません。
- 一度に一つのスライス。 1サイクルにつき、1つのシーム、1つのテスト、1つの最小限の実装。
- リファクタリングはループの一部ではない。 リファクタリングはレビューステージ(
code-reviewスキルを参照)に属し、レッド→グリーンの実装サイクルには含まれません。