32章 TDDを身につける
TDDは知識ではなく“習慣”である
フェーズ1:意識的TDD
- 毎回「先にテスト…」と考える
- ぎこちない
- 遅く感じる
フェーズ2:半自動TDD
- Redを書くと落ち着く
- Greenを急ぐ癖がつく
- Refactorが自然に挟まる
フェーズ3:無意識TDD
- 書き始める前にテストが浮かぶ
- 実装の前にAPIが決まる
- 「怖い変更」が消える
LaravelでのTDDを意識した構成
原則① Controller は「HTTP変換層」
Controller は ロジックを書かない。
HTTP Request
↓
Controller(入力変換・呼び出し)
↓
UseCase / Service(業務ロジック)
↓
Domain / Repository
原則② TDD は「クラス境界」を作るために使う
- テストしづらい → 設計が悪い
- モックが増える → 責務が多い
TDD に向いた基本レイヤ構成例
app/
├─ Http/
│ └─ Controllers/
│ └─ UserController.php
│
├─ UseCase/ ← TDDの主戦場
│ └─ CreateUser.php
│
├─ Domain/
│ ├─ Entity/
│ │ └─ User.php
│ ├─ ValueObject/
│ │ └─ Email.php
│ └─ Repository/
│ └─ UserRepository.php (interface)
│
├─ Infrastructure/
│ └─ Eloquent/
│ └─ EloquentUserRepository.php
TDDを意識した実装
① Domain / UseCase の Unit Test
② Repository の Unit / Integration Test
③ 最後に Controller の Feature Test
アンチパターン
- Feature テストから書く
- DBあaりで全部検証
テスト系のディレクトリ設計例
tests/
├─ Unit/
│ ├─ UseCase/
│ │ └─ CreateUserTest.php
│ ├─ Domain/
│ │ ├─ Entity/
│ │ │ └─ UserTest.php
│ │ └─ ValueObject/
│ │ └─ EmailTest.php
│ └─ Infrastructure/
│ └─ Eloquent/
│ └─ EloquentUserRepositoryTest.php
│
└─ Feature/
└─ Http/
└─ UserControllerTest.php
####「テストは設計図の鏡」
テストのディレクトリ構造を見るだけで、どこにロジックがあるか
どこが重要か
どこが境界か
が分かるようになります。
Unit / Feature の意味がブレない
| 種類 | 目的 |
|---|---|
| Unit | 純PHP・高速 |
| Feature | HTTP / Laravel 統合 |
よくある質問と落とし穴
Q1. Unit に DB テストを書いてもいい?
おすすめしません。
- PHPUnit の速度が死ぬ
- TDD リズムが崩れる
DBが必要なら tests/Unit/Infrastructure か Feature
Q2. UseCase テストは Feature じゃだめ?
ダメではないが もったいない
理由:
- 遅い
- ノイズが多い
- 設計が育たない
Q3. InMemory Repository のテストは?
不要
- テストのための道具
- テストしない
Q4. tests 配下を app に完全一致させるべき?
概念的に一致でOK
例:
app/UseCase/CreateUser.php
tests/Unit/UseCase/CreateUserTest.php
TDDはアーキテクチャか?
TDDはアーキテクチャではない。しかし、アーキテクチャを“生み出す力”を持っている。
アーキテクチャの定義
一般にアーキテクチャとは:
- コンポーネントの分割
- 依存関係の方向
- 境界の定義
- 変更容易性の戦略
であり、
TDD の正体
- 開発プロセス
- フィードバックループ
- 思考法
- 設計を進化させるための制約
最後に
こういった技術系書籍を読むにあたって、非常に読みづらさを感じることがあります。その場合ChatGPTなどの助けを借りることで学習しやすさが格段にアップしました。
さらにアウトプットすることで定着のしやすくなります。