第42回: FeatureテストとUnitテストの使い分け — テストを「目的別」に書き分ける

章: 第5章: テストと品質管理

すべてのテストをUnitテストで書こうとして、HTTP周りの検証が難しくなっていませんか?

「ユーザーが投稿を作成できるか」という検証は、Unitテストだけでは限界があります。Laravelでは、ユーザー操作の流れを検証するFeatureテストと、個別ロジックを検証するUnitテストを使い分けることで、テストが過不足なく整います。

テストの種類を使い分けないと何が起きるか

Unitテストだけでは「各クラスは動くが、つなぎ合わさると壊れる」問題を見逃します。Featureテストだけでは、実行時間が長くなり小さな失敗箇所が特定しにくくなります。両者を目的に合わせて使い分けることが重要です。

FeatureテストとUnitテストの比較

観点 Featureテスト Unitテスト
検証対象 HTTPリクエスト全体・DB・ルーティング 単一クラス・メソッドの入出力
実行速度 遅い(DBアクセスあり) 速い(外部依存なし)
書く場面 APIエンドポイント・フォーム送信 計算ロジック・バリデーション規則
向いている検証 「ユーザーが○○できるか」 「このメソッドが○○を返すか」

チェックポイント: actingAs($user) を使ったFeatureテストでは、認証が必要なエンドポイントに正しいユーザーでアクセスできているかを確認しましょう。assertDatabaseHas() でDBへの書き込みも確認し、リダイレクト先まで一連の流れをテストするのが理想です。

コードサンプル


<?php
// Featureテスト: HTTPリクエスト全体を通す
class PostControllerTest extends TestCase {
    public function test_user_can_create_post(): void {
        $user = User::factory()->create();
        $response = $this->actingAs($user)->post('/posts', [
            'title' => 'テスト記事',
            'body'  => '本文',
        ]);
        $response->assertRedirect('/posts');
        $this->assertDatabaseHas('posts', ['title' => 'テスト記事']);
    }
}
// Unitテスト: 単一クラス・関数だけを検証

まとめ & 次のステップ

  • Featureテストはエンドツーエンドの動作を、Unitテストは単一ロジックを検証します
  • actingAs() で認証済みユーザーとしてHTTPリクエストを送れます
  • assertDatabaseHas() / assertDatabaseMissing() でDB状態を検証できます
  • 速いフィードバックが必要なビジネスロジックはUnitテストを優先しましょう
  • 両テストを組み合わせてCI上で自動実行する仕組みを整えましょう

次回は コードカバレッジの測り方 を学びます。テストが不足している箇所を客観的に可視化する方法を整理しましょう。

Related Articles