テスト駆動開発
テストを先に書き、テストが通るコードを実装し、リファクタリングするサイクルで開発を進める手法
テスト開発手法
テスト駆動開発とは
テスト駆動開発 (Test-Driven Development, TDD) は、Kent Beck が 2002 年に体系化した開発手法で、Red → Green → Refactor の 3 ステップを繰り返してコードを書く。「テストを先に書く」ことで、設計の品質とテストカバレッジを同時に向上させる。
Red → Green → Refactor
1. Red: 失敗するテストを書く
2. Green: テストが通る最小限のコードを書く
3. Refactor: コードを整理する (テストは通ったまま)
→ 1 に戻る
実践例
// Step 1: Red - 失敗するテストを書く
test('10,000円以上で10%割引', () => {
expect(calculateDiscount(15000)).toBe(1500);
});
// → ReferenceError: calculateDiscount is not defined
// Step 2: Green - テストが通る最小限のコードを書く
function calculateDiscount(total: number): number {
if (total >= 10000) return total * 0.1;
return 0;
}
// → ✅ テスト通過
// Step 3: Refactor - コードを整理
const DISCOUNT_THRESHOLD = 10000;
const DISCOUNT_RATE = 0.1;
function calculateDiscount(total: number): number {
if (total >= DISCOUNT_THRESHOLD) return total * DISCOUNT_RATE;
return 0;
}
// → ✅ テスト通過 (リファクタリング後も)
// Step 1 (次のサイクル): 新しいテストを追加
test('会員は15%割引', () => {
expect(calculateDiscount(15000, true)).toBe(2250);
});
// → Red → Green → Refactor ...
TDD のメリット
- テストカバレッジが自然に高くなる (テストを先に書くため)
- 設計が改善される (テストしやすい = 疎結合な設計)
- リファクタリングが安全にできる (テストが回帰を検出)
- 過剰な実装を防ぐ (テストが通る最小限のコードだけ書く)
TDD が難しいケース
| ケース | 理由 | 代替アプローチ |
|---|---|---|
| UI のスタイリング | 見た目のテストが困難 | ビジュアルリグレッションテスト |
| 外部 API との連携 | モックの設定が複雑 | 結合テストで補完 |
| 探索的な開発 | 仕様が不明確 | スパイクで仕様を固めてから TDD |
| レガシーコード | テストが書きにくい構造 | まずリファクタリングしてテスタブルに |
TDD と BDD の違い
| 手法 | テストの記述 | 焦点 |
|---|---|---|
| TDD | expect(calculateDiscount(15000)).toBe(1500) |
実装の正しさ |
| BDD | Given 15000円の注文 When 割引計算 Then 1500円 |
ビジネス要件の充足 |
BDD (Behavior-Driven Development) は TDD の発展形で、ビジネス要件をテストとして記述する。
Lambda での TDD
Lambda ハンドラーは純粋関数に近い (入力 → 出力) ため、TDD と相性が良い。
// テストを先に書く
test('正常な注文リクエストで 201 を返す', async () => {
const event = createApiEvent({ body: JSON.stringify({ item: 'Book', qty: 1 }) });
const result = await handler(event);
expect(result.statusCode).toBe(201);
});
実務での活用方法は関連書籍にも詳しい。