0%
Claude Code攻略#Claude Code#TDD#テスト

テスト駆動開発 with Claude Code【TDD実践ガイド】

Claude Codeを使ったテスト駆動開発(TDD)の実践方法。Red-Green-Refactorサイクルを効率的に回すテクニック。

||12分で読める

TDDとは

テスト駆動開発(TDD: Test-Driven Development)は:

  1. Red: 失敗するテストを書く
  2. Green: テストが通る最小限のコードを書く
  3. Refactor: コードを改善する

このサイクルを繰り返す開発手法です。

なぜClaude Code × TDDなのか

Claude Codeを使うと:

  • テストコードの生成が速い
  • 実装コードも自動生成
  • リファクタリングも任せられる

人間が「何を作りたいか」を考え、Claudeが「テスト→実装→改善」を実行します。

TDDの実践フロー

STEP 1: テストファイルを作成

calcPrice関数をTDDで作りたい。

要件:
- 通常価格を返す
- 数量が10以上なら10%割引
- 数量が100以上なら20%割引

まず失敗するテストを書いて。

Claudeが生成するテスト:

// src/lib/pricing.test.ts
import { calcPrice } from './pricing'

describe('calcPrice', () => {
  it('通常価格を返す(数量1)', () => {
    expect(calcPrice(1000, 1)).toBe(1000)
  })

  it('数量が10以上なら10%割引', () => {
    expect(calcPrice(1000, 10)).toBe(9000) // 1000 * 10 * 0.9
  })

  it('数量が100以上なら20%割引', () => {
    expect(calcPrice(1000, 100)).toBe(80000) // 1000 * 100 * 0.8
  })
})

STEP 2: テストを実行(Red)

テストを実行して。失敗することを確認。

結果:

FAIL src/lib/pricing.test.ts
  calcPrice
    ✕ 通常価格を返す(数量1)
    ✕ 数量が10以上なら10%割引
    ✕ 数量が100以上なら20%割引

Test Suites: 1 failed
Tests: 3 failed

テストが失敗することを確認(関数がまだ存在しないため)。

STEP 3: 最小限の実装(Green)

テストが通る最小限のコードを書いて。
過度な設計は不要。まずテストを通すことだけ考えて。

Claudeが生成:

// src/lib/pricing.ts
export function calcPrice(unitPrice: number, quantity: number): number {
  const total = unitPrice * quantity

  if (quantity >= 100) {
    return total * 0.8
  }
  if (quantity >= 10) {
    return total * 0.9
  }
  return total
}

STEP 4: テスト実行(Green確認)

テストを実行して。

結果:

PASS src/lib/pricing.test.ts
  calcPrice
    ✓ 通常価格を返す(数量1)
    ✓ 数量が10以上なら10%割引
    ✓ 数量が100以上なら20%割引

Test Suites: 1 passed
Tests: 3 passed

STEP 5: リファクタリング(Refactor)

テストが通った状態を維持しながら、コードを改善して。
- 定数の抽出
- 型の強化
- 可読性の向上

改善後:

// src/lib/pricing.ts
const DISCOUNT_TIERS = [
  { minQuantity: 100, discount: 0.2 },
  { minQuantity: 10, discount: 0.1 },
] as const

export function calcPrice(unitPrice: number, quantity: number): number {
  const total = unitPrice * quantity
  const tier = DISCOUNT_TIERS.find(t => quantity >= t.minQuantity)
  return tier ? total * (1 - tier.discount) : total
}
リファクタリング後もテストが通ることを確認して。

実践例: ユーザー登録機能

要件定義

ユーザー登録機能をTDDで作りたい。

要件:
- メールアドレスは必須、形式チェック
- パスワードは8文字以上
- 同じメールアドレスは登録不可
- 登録成功でユーザーIDを返す

まず失敗するテストを書いて。

テストコード

// src/services/user.test.ts
import { registerUser } from './user'

describe('registerUser', () => {
  beforeEach(() => {
    // テスト用DBをリセット
  })

  describe('バリデーション', () => {
    it('メールアドレスがない場合はエラー', async () => {
      await expect(
        registerUser({ email: '', password: 'password123' })
      ).rejects.toThrow('Email is required')
    })

    it('メールアドレスの形式が不正な場合はエラー', async () => {
      await expect(
        registerUser({ email: 'invalid', password: 'password123' })
      ).rejects.toThrow('Invalid email format')
    })

    it('パスワードが8文字未満の場合はエラー', async () => {
      await expect(
        registerUser({ email: 'test@example.com', password: 'short' })
      ).rejects.toThrow('Password must be at least 8 characters')
    })
  })

  describe('登録処理', () => {
    it('正常に登録できる', async () => {
      const result = await registerUser({
        email: 'test@example.com',
        password: 'password123'
      })
      expect(result.userId).toBeDefined()
    })

    it('同じメールアドレスは登録不可', async () => {
      await registerUser({
        email: 'test@example.com',
        password: 'password123'
      })
      await expect(
        registerUser({
          email: 'test@example.com',
          password: 'password456'
        })
      ).rejects.toThrow('Email already exists')
    })
  })
})

実装を依頼

このテストが通る実装を書いて。

TDDのコツ

コツ1: テストは具体的に

❌ 「ユーザー登録のテストを書いて」
✅ 「メールアドレスが空の場合にエラーを返すテストを書いて」

コツ2: 一度に1つのテスト

テストを1つずつ追加して、その都度実装を更新して。

コツ3: エッジケースを忘れずに

このメソッドのエッジケースを洗い出して、テストを追加して:
- 空の入力
- 境界値
- 異常な入力

コツ4: モックを活用

外部API呼び出しをモックしてテストを書いて。

テストの種類と使い分け

ユニットテスト

calcPrice関数の単体テストを書いて。
外部依存はモック。

統合テスト

API エンドポイント /api/users の統合テストを書いて。
実際のDBを使用(テスト用)。

E2Eテスト

ユーザー登録〜ログインまでのE2Eテストを書いて。
Playwrightを使用。

よくある質問

Q: どこまでテストを書くべき?

このプロジェクトで特に重要な部分を教えて。
その部分を優先的にテストしたい。

一般的な優先順位:

  1. ビジネスロジック(計算、判定)
  2. API エンドポイント
  3. 複雑な状態管理
  4. UIコンポーネント

Q: テストが多くてメンテが大変

このテストファイルをリファクタリングして:
- 重複を排除
- テストヘルパーを作成
- 可読性を向上

次のステップ

TDDの基本をマスターしました!

次は、より高度なデバッグテクニックを学びましょう。

Claude Codeデバッグ上級編

まとめ

  • TDD = Red → Green → Refactor のサイクル
  • まず失敗するテストを書く
  • テストが通る最小限のコードを実装
  • テストが通った状態でリファクタリング
  • Claudeにテスト生成→実装→改善を任せる
  • 要件を明確にするほどテストの品質が上がる
シェア:

参考文献・引用元

Claude Code攻略の他の記事

他のカテゴリも見る