はじめに
Laravel では ユニットテストとフィーチャーテストの二系統が用意されています。ユニットテストが「メソッド単位」でロジックを検証するのに対し、フィーチャーテストは HTTP リクエストからレスポンスまでのフローをアプリ全体で検証し、データベースを含む実行環境を通して期待どおりに動くかを確認します。ここではフィーチャーテストの基本から、テスト用データベースの構築・運用方法までを体系的に解説します。
1. フィーチャーテストの基礎
| 項目 | 内容 |
|---|---|
| 生成コマンド | php artisan make:test PostCreationTest ( --unit を付けないと tests/Feature 配下に作成) |
| ベースクラス | Tests\TestCase(Illuminate\Foundation\Testing\RefreshDatabase などのトレイトを併用) |
| 主な API | get() / post() / putJson() などのリクエストメソッドと assertStatus() / assertSee() / assertJson() 系アサーション |
例: 投稿作成のフローを検証する
フィーチャーテストでは HTTP レイヤと永続層が同時に検証対象になるため、テスト用データベース環境が不可欠です。laravel.comlaravel.com
2. テスト用データベースの構成
2.1 .env.testing と phpunit.xml
.env.testing と phpunit.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 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 例:
-
失敗時に
--compactを付けると 失敗テストだけを再実行でき、デバッグ効率が上がります。
6. よくある落とし穴と対策
| 症状 | 原因 | 解決策 |
|---|---|---|
| テスト開始時に「データベースが見つからない」 | .env.testing が読み込まれていない |
phpunit.xml の <server name="APP_ENV" value="testing"/> を確認 |
| テストが極端に遅い | RefreshDatabase でフルマイグレーション |
インメモリ SQLite または DatabaseTransactions を検討 |
| 外部サービスに実リクエストが飛ぶ | モックが不足 | Http::fake()・Event::fake() で置き換え |
まとめ
-
フィーチャーテストは HTTP~DB まで横断で検証し、実アプリに最も近い動作確認を実現。
-
テスト用 DBは
.env.testingで分離し、RefreshDatabaseなどのトレイトでスキーマを安全に初期化。 -
Laravel 11 では インメモリ SQLite の最適化により速度が大幅向上。
-
ファクトリ+アサーションで データ整合性を高粒度にチェック。
-
並列テストと CI 連携で 開発フローへ自然に組み込み、品質と開発速度を両立。
これらを押さえることで、Laravel アプリの信頼性を高めつつ、テスト実行コストも最小化できます。
ChatGPT4o 生成日:2025/06/23