【Laravel】機能テスト(Feature Test)でよく使う定番コード&アサーション

Laravel

Laravelで機能テストを書く際に、「あれ、ログイン状態をシミュレートするのってどう書くんだっけ?」「リダイレクトの検証は?」と毎回調べる時間を減らすための備忘録です。

テストの基本構成(Arrange / Act / Assert)に沿って、よく使う定番のコードパターンをまとめました。

1. 事前準備(Arrange)によく使うコード

データの作成(Factory)

テスト用のデータをデータベースに作成します。

PHP

// ユーザーを1件作成
$user = User::factory()->create();

// 属性を指定してデータを作成(例:特定のユーザーに紐づく記事)
$post = Post::factory()->create([
    'user_id' => $user->id,
    'title' => 'テストタイトル',
]);

// 複数件まとめて作成
$posts = Post::factory()->count(3)->create();

2. リクエストの送信(Act)によく使うコード

ログイン状態のシミュレート

actingAs を挟むことで、指定したユーザーでログインした状態のリクエストを送れます。

PHP

// ログインしてGETリクエスト
$response = $this->actingAs($user)->get(route('posts.index'));

// ログインしてPOSTリクエスト(データ送信)
$response = $this->actingAs($user)->post(route('posts.store'), [
    'title' => '新しい記事',
    'body' => '記事の本文です。',
]);

ゲスト(未ログイン)状態でのリクエスト

PHP

// 単にリクエストを送るだけ(未ログイン状態の挙動確認に)
$response = $this->get(route('posts.index'));

3. 結果の検証(Assert)によって使い分けるコード

HTTPステータス・画面遷移の検証

PHP

// 200 OK(画面が正常に表示されたか)
$response->assertStatus(200);
// または簡易表記
$response->assertOk();

// 302 リダイレクト(保存処理後のリダイレクトなど)
$response->assertStatus(302);
// 特定のURLへのリダイレクトを検証
$response->assertRedirect(route('posts.index'));

// 403 Forbidden(権限エラー)
$response->assertStatus(403);
// 404 Not Found(ページが見つからない)
$response->assertStatus(404);

画面表示(HTML)の検証

PHP

// 画面内に指定したテキストが含まれているか
$response->assertSee('記事一覧');
$response->assertSee($post->title);

// 画面内に指定したテキストが「含まれていない」か(非公開記事の非表示テストなど)
$response->assertDontSee('秘密のテキスト');

データベース(DB)の検証

PHP

// 指定したデータがDBに存在するか(追加・更新の検証)
$this->assertDatabaseHas('posts', [
    'title' => '新しい記事',
    'user_id' => $user->id,
]);

// 指定したデータがDBに存在しないか(削除の検証)
$this->assertDatabaseMissing('posts', [
    'id' => $post->id,
]);

バリデーションエラーの検証

PHP

// セッションにエラー(バリデーション失敗)があるか
$response->assertSessionHasErrors(['title']);

// エラーがないことを検証
$response->assertSessionHasNoErrors();

4. 【実例】よくあるテストケースのテンプレート

パターンA:一覧画面の表示テスト(ログイン必須)

PHP

public function test_user_can_access_posts_index()
{
    // 1. 準備
    $user = User::factory()->create();
    $post = Post::factory()->create(['user_id' => $user->id]);

    // 2. 実行
    $response = $this->actingAs($user)->get(route('posts.index'));

    // 3. 検証
    $response->assertOk();
    $response->assertSee($post->title);
}

パターンB:新規作成処理のテスト(バリデーション通過)

PHP

public function test_user_can_create_post()
{
    $user = User::factory()->create();
    $params = [
        'title' => '新規タイトル',
        'body' => '新規本文',
    ];

    $response = $this->actingAs($user)->post(route('posts.store'), $params);

    // 一覧画面へリダイレクトされることを検証
    $response->assertRedirect(route('posts.index'));
    
    // DBにデータが保存されたか検証
    $this->assertDatabaseHas('posts', [
        'user_id' => $user->id,
        'title' => '新規タイトル',
    ]);
}

パターンC:未ログインユーザーのアクセス制限テスト

PHP

public function test_guest_cannot_access_posts_index()
{
    // ログインせずリクエスト
    $response = $this->get(route('posts.index'));

    // ログイン画面へリダイレクトされることを検証
    $response->assertRedirect(route('login'));
}

まとめ

Laravelの機能テストは、「誰が」「どこにアクセスして(何を送信して)」「どうなったか」 を順番に書いていくだけなので、基本パターンさえ押さえればサクサク書けるようになります。

コメント