#27 Laravel基礎
フィーチャーテストを書く
テストとは
Laravelには2種類のテストがあります。
| 種類 | 内容 |
|---|---|
| フィーチャーテスト? HTTPリクエストを模倣してアプリ全体の動作を確認するテスト。ルートからDBまで実際に動かして結果を検証する。 | HTTPリクエスト〜レスポンスまでアプリ全体を検証 |
| ユニットテスト? 個々のクラスやメソッドを独立して検証するテスト。外部依存を切り離してロジック単体が正しく動くかを確認する。 | 個々のクラス・メソッドを単独で検証 |
この回は実務でよく書くフィーチャーテストから始めます。
テストの準備
データベース設定
テスト用に SQLite のインメモリDBを使うと速くて独立した環境が作れます。
# 📁 .env.testing(テスト専用の .env)
DB_CONNECTION=sqlite
DB_DATABASE=:memory:
または phpunit.xml に設定します。
<!-- 📁 phpunit.xml -->
<php>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="MAIL_MAILER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
</php>
RefreshDatabase トレイト
テストクラスに RefreshDatabase を付けると、各テストの前後にDBをリセットしてくれます。
use Illuminate\Foundation\Testing\RefreshDatabase;
class PostTest extends TestCase
{
use RefreshDatabase; // ← これを付ける
}
最初のフィーチャーテスト
php artisan make:test PostTest
tests/Feature/PostTest.php が生成されます。
<?php
// 📁 tests/Feature/PostTest.php
namespace Tests\Feature;
use App\Models\Post;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class PostTest extends TestCase
{
use RefreshDatabase;
// 投稿一覧が表示されるか
public function test_投稿一覧を表示できる(): void
{
Post::factory()->published()->count(3)->create();
$response = $this->get('/posts');
$response->assertStatus(200);
$response->assertViewHas('posts');
}
// 未ログインではフォームにアクセスできないか
public function test_未ログインでは投稿フォームにアクセスできない(): void
{
$response = $this->get('/posts/create');
$response->assertRedirect('/login');
}
// ログイン済みで投稿を作成できるか
public function test_ログインユーザーは投稿を作成できる(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)
->post('/posts', [
'title' => 'テスト投稿',
'body' => 'テスト本文',
]);
$response->assertRedirect('/posts');
$this->assertDatabaseHas('posts', [
'title' => 'テスト投稿',
'user_id' => $user->id,
]);
}
}
よく使うアサーション
// HTTPステータス
$response->assertStatus(200);
$response->assertOk(); // 200
$response->assertCreated(); // 201
$response->assertNotFound(); // 404
$response->assertForbidden(); // 403
$response->assertRedirect('/url');
// ビュー
$response->assertViewIs('posts.index');
$response->assertViewHas('posts');
$response->assertViewHas('posts', fn ($posts) => $posts->count() === 3);
// レスポンスの内容
$response->assertSee('テスト投稿');
$response->assertDontSee('削除済み');
// JSON
$response->assertJson(['status' => 'ok']);
$response->assertJsonPath('data.name', 'テスト');
// DB
$this->assertDatabaseHas('posts', ['title' => 'テスト']);
$this->assertDatabaseMissing('posts', ['title' => '削除済み']);
$this->assertDatabaseCount('posts', 3);
ログイン状態のテスト
$user = User::factory()->create();
// $user としてログインした状態でリクエストを送る
$this->actingAs($user)->get('/dashboard');
// 認証済みか確認
$this->assertAuthenticated();
// 未認証か確認
$this->assertGuest();
バリデーションエラーのテスト
public function test_タイトル未入力はバリデーションエラーになる(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/posts', [
'title' => '', // ← 空
'body' => 'テスト本文',
]);
$response->assertSessionHasErrors('title');
$this->assertDatabaseCount('posts', 0);
}
テストを実行する
# 全テストを実行
php artisan test
# 特定のファイルのみ
php artisan test tests/Feature/PostTest.php
# テスト名でフィルター
php artisan test --filter="投稿を作成できる"
# 並列実行(高速)
php artisan test --parallel
まとめ
RefreshDatabaseでテストごとにDBをリセットする$this->get(),$this->post()でHTTPリクエストをシミュレートするactingAs($user)でログイン状態を作れるassertDatabaseHas()でDBへの書き込みを検証できるassertSessionHasErrors()でバリデーションエラーを確認できる
次回はユニットテストとモックを使ったテストを学びます。