テストパターン
信頼性の高いテストスイートの原則です。
1. テストのピラミッド
/\ E2E (Few)
/ \ Critical flows
/----\
/ \ Integration (Some)
/--------\ API, DB queries
/ \
/------------\ Unit (Many)
Functions, classes
2. AAA パターン
| ステップ | 目的 |
|---|
| Arrange | テストデータを準備する |
| Act | テスト対象のコードを実行する |
| Assert | 結果を検証する |
3. テストタイプの選択
それぞれの使いどころ
| タイプ | 最適な対象 | 速度 |
|---|
| Unit | 純粋関数、ロジック | 高速(<100ms) |
| Integration | API、DB、サービス | 中程度 |
| E2E | 重要なユーザーフロー | 低速 |
4. 単体テストの原則
優れた単体テスト
| 原則 | 意味 |
|---|
| 高速 | 1 件あたり < 100ms |
| 分離されている | 外部依存がない |
| 再現可能 | 常に同じ結果になる |
| 自己検証可能 | 手動での検証が不要 |
| 適時 | コードと同時に書かれている |
単体テストの対象
| テストするもの | テストしないもの |
|---|
| ビジネスロジック | フレームワークのコード |
| エッジケース | サードパーティーライブラリ |
| エラー処理 | 単純なゲッター |
5. 結合テストの原則
テストする対象
| 領域 | 焦点 |
|---|
| API エンドポイント | リクエスト/レスポンス |
| データベース | クエリ、トランザクション |
| 外部サービス | コントラクト |
セットアップ/ティアダウン
| フェーズ | アクション |
|---|
| 全テストの前 | リソースに接続する |
| 各テストの前 | 状態をリセットする |
| 各テストの後 | クリーンアップする |
| 全テストの後 | 接続を切断する |
6. モックの原則
モックを使う場面
| モックするもの | モックしないもの |
|---|
| 外部 API | テスト対象のコード |
| データベース(単体テスト) | 単純な依存関係 |
| 時刻/乱数 | 純粋関数 |
| ネットワーク | メモリ内ストア |
モックの種類
| 種類 | 用途 |
|---|
| スタブ | 固定値を返す |
| スパイ | 呼び出しを追跡する |
| モック | 期待値を設定する |
| フェイク | 簡略化した実装 |
7. テストの構成
命名
| パターン | 例 |
|---|
| 期待する振る舞い | "エラーを返すこと(〜の場合)" |
| 条件 | "ユーザーが見つからない場合..." |
| Given-when-then | "X が与えられたとき、Y を実行すると、Z になる" |
グループ化
| レベル | 用途 |
|---|
| describe | 関連するテストをグループ化する |
| it/test | 個別のケース |
| beforeEach | 共通のセットアップ |
8. テストデータ
戦略
| アプローチ | 用途 |
|---|
| ファクトリー | テストデータを生成する |
| フィクスチャ | 事前定義されたデータセット |
| ビルダー | 流れるようにオブジェクトを作成する |
原則
- 現実的なデータを使用する
- 重要でない値はランダム化する(faker)
- 共通のフィクスチャを共有する
- データを最小限にする
9. ベストプラクティス
| プラクティス | 理由 |
|---|
| 1 テストにつき 1 つのアサーション | 失敗理由が明確になる |
| テストを独立させる | 実行順序に依存しない |
| テストを高速にする | 頻繁に実行できる |
| 説明的な名前を付ける | 説明を兼ねたドキュメントになる |
| クリーンアップする | 副作用を避ける |
10. アンチパターン
| ❌ しないこと | ✅ すること |
|---|
| 実装をテストする | 振る舞いをテストする |
| テストコードを重複させる | ファクトリーを使う |
| 複雑なテストセットアップ | 簡素化するか、分割する |
| 不安定なテストを無視する | 根本原因を修正する |
| クリーンアップを省略する | 状態をリセットする |
覚えておきましょう: テストはドキュメントです。テストを読んでもコードの動作が理解できない場合は、書き直してください。