テスト駆動開発
機能追加やバグ修正は、テストをフィードバックループとして使用し、1つの垂直スライスずつ進めます。
核心原則
テストは実装の詳細ではなく、公開インターフェースを通じて振る舞いを検証します。リファクタリングを行っても振る舞いが変わっていないのにテストが壊れる場合、そのテストは間違っています。
アンチパターン:水平スライス
すべてのテストを最初に書き、その後すべての実装を行ってはいけません。1つのテストを書き、それをパスさせ、それを繰り返します。
誤り: RED test1, test2, test3 -> GREEN impl1, impl2, impl3
正解: RED test1 -> GREEN impl1 -> RED test2 -> GREEN impl2 -> ...
ワークフロー
1. 計画
- ユーザーとインターフェースの変更を確認します。
- テストする振る舞いを確認します。すべてをテストすることはできません。
- 振る舞いを観測可能な結果としてリスト化し、実装手順としてリスト化しないでください。
- コードを書く前にユーザーの承認を得てください。
2. トレーサー弾
1つの振る舞いに対して1つのテストを書きます。それが失敗するのを確認します。それをパスさせるための最小限のコードを書きます。
3. インクリメンタルループ
残りの各振る舞いに対して、以下を繰り返します:
- 次のテストを書きます。
- 最小限のコードでそれをパスさせます。
- 将来のテストを見越さないでください。
4. リファクタリング
すべてのテストがパスした後:
- 重複を抽出します。
- モジュールを深くします:小さなインターフェース、深い実装。
- リファクタリングの各ステップ後にテストを実行します。
RED(テスト失敗)の状態では決してリファクタリングを行わないでください。
サイクルごとのチェックリスト
- テストは実装ではなく振る舞いを記述している
- テストは公開インターフェースを使用している
- テストは内部リファクタリング後も有効である
- コードはこのテストに対して最小限である
- 推測による機能は追加されていない
ルール
- 新しい振る舞いに対しては、実装の前にテストを書きます。
- 型ヒントと明確な名前を使用します。
- 関数は小さく、単一目的に保ちます。
- 明確なエラーメッセージとともに早期に失敗します。