フィーチャーテストとテスト用データベース

はじめに

Laravel では ユニットテストフィーチャーテストの二系統が用意されています。ユニットテストが「メソッド単位」でロジックを検証するのに対し、フィーチャーテストは HTTP リクエストからレスポンスまでのフローをアプリ全体で検証し、データベースを含む実行環境を通して期待どおりに動くかを確認します。ここではフィーチャーテストの基本から、テスト用データベースの構築・運用方法までを体系的に解説します。


1. フィーチャーテストの基礎

項目 内容
生成コマンド php artisan make:test PostCreationTest
--unit を付けないと tests/Feature 配下に作成)
ベースクラス Tests\TestCaseIlluminate\Foundation\Testing\RefreshDatabase などのトレイトを併用)
主な API get() / post() / putJson() などのリクエストメソッドと
assertStatus() / assertSee() / assertJson() 系アサーション

例: 投稿作成のフローを検証する

php
<?php namespace Tests\Feature; use Tests\TestCase; use Illuminate\Foundation\Testing\RefreshDatabase; use App\Models\Post; class PostCreationTest extends TestCase { use RefreshDatabase; // 後述 public function test_user_can_create_post() { $payload = ['title' => 'テスト投稿', 'body' => '本文']; $response = $this->post('/posts', $payload); $response->assertStatus(302); // リダイレクトを想定 $this->assertDatabaseHas('posts', [ // DB への書き込みを確認 'title' => 'テスト投稿', ]); } }

フィーチャーテストでは HTTP レイヤと永続層が同時に検証対象になるため、テスト用データベース環境が不可欠です。laravel.comlaravel.com


2. テスト用データベースの構成

2.1 .env.testingphpunit.xml

ファイル 主な役割
.env.testing DB_CONNECTION=sqlite
DB_DATABASE=:memory: など、テスト専用の接続設定を定義
phpunit.xml <env name="APP_ENV" value="testing"/> 等で .env.testing を読むよう指定
  • SQLite インメモリはスピードが最優先の場面で有力。Laravel 11 では PDO インスタンスを再利用する最適化が入り、テスト時間が約半分に短縮されました。laravel.com

  • 本番と同系統の DB(MySQL/PostgreSQL 等)で動作差異を検証したい場合は Docker コンテナを立て、DB_HOST=mysql_test などに切り替えます。

2.2 データベースを初期化するトレイト

トレイト 挙動 長所 / 短所
RefreshDatabase テスト開始時に migrate:fresh を実行し、
各テスト前後でトランザクションを張る
実環境に近いスキーマを再生成。重いが安全。
DatabaseTransactions 各テストを 単一トランザクションで実行し、終了時にロールバック 高速だが、外部接続や一部ドライバでは使用不可。
DatabaseMigrations 各テストで migrate / rollback を実行 レガシー用途。近年は RefreshDatabase が推奨。

RefreshDatabase で「毎回フルマイグレーションは遅い」と感じたら、インメモリ SQLite+ Laravel 11 の最適化と併用すると高速化できます。laraveldaily.comstackoverflow.com


3. モデルファクトリとシーディング

  • ファクトリ: php artisan make:factory PostFactory

    php
    Post::factory()->count(10)->create();
  • テストごとのシード: php artisan make:seeder TestDatabaseSeeder を作成し、
    テストクラスに use RefreshDatabase; protected $seed = true; を書くと自動実行。

  • 大量データのベンチマークN+1 検出にも有効。


4. データベースアサーション

メソッド 用途
assertDatabaseHas($table, $data) レコード存在確認
assertDatabaseMissing($table, $data) レコード不存在確認
assertDatabaseCount($table, $expected) 件数確認(Laravel 8.69+)
assertSoftDeleted($table, $data) ソフトデリート確認

これらは Eloquent を介さずテーブルを直接検証するため、リポジトリ層のバグを迅速に発見できます。laravel.com


5. パラレルテストと CI への組み込み

  • php artisan test --parallel でコア数ぶん並列実行。DB は 接続ごとにスキーマをコピーdatabase-test-0.sqlite 等)して干渉を防止。

  • GitHub Actions 例:

    yaml
    - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: php-version: '8.3' coverage: xdebug - run: composer install --prefer-dist --no-progress - run: php artisan test --parallel
  • 失敗時に --compact を付けると 失敗テストだけを再実行でき、デバッグ効率が上がります。


6. よくある落とし穴と対策

症状 原因 解決策
テスト開始時に「データベースが見つからない」 .env.testing が読み込まれていない phpunit.xml<server name="APP_ENV" value="testing"/> を確認
テストが極端に遅い RefreshDatabase でフルマイグレーション インメモリ SQLite または DatabaseTransactions を検討
外部サービスに実リクエストが飛ぶ モックが不足 Http::fake()Event::fake() で置き換え

まとめ

  1. フィーチャーテストは HTTP~DB まで横断で検証し、実アプリに最も近い動作確認を実現。

  2. テスト用 DB.env.testing で分離し、RefreshDatabase などのトレイトでスキーマを安全に初期化。

  3. Laravel 11 では インメモリ SQLite の最適化により速度が大幅向上。

  4. ファクトリ+アサーションで データ整合性を高粒度にチェック。

  5. 並列テストと CI 連携で 開発フローへ自然に組み込み、品質と開発速度を両立。

これらを押さえることで、Laravel アプリの信頼性を高めつつ、テスト実行コストも最小化できます。

ChatGPT4o 生成日:2025/06/23