📌

【Laravel】PHPUnitでの基本的なテスト構文

2023/09/18に公開

LaravelでPHPUnitを使用した際の基本的な書き方について
学んだことを備忘録として残します。

環境

  • PHP 8.2.7
  • Laravel 10.22.0
  • PHPUnit 10.3.3

テスト実行

# すべてのテストを実行
php artisan test

# 特定のクラスやメソッド名を部分一致で指定
php artisan test --filter=testRegisterTask

# 特定のファイルを指定
php artisan test tests/Feature/TaskControllerTest.php

# 特定のフォルダを指定
php artisan test tests/Feature

実行結果例

PASS  Tests\Feature\TaskControllerTest
✓ register task 0.06s 

Tests:    1 passed (3 assertions)
Duration: 1.50s

OK (1 test, 3 assertions)とは、テストが書かれたクラスが一つで
合計3つのアサーション(assertion)を実行したという意味です。
※assertionは、一つ一つの実際のテスト内容のことを指します。

命名規則

クラス名

PHPUnitはコマンド実行時にクラス名がTestで終えるクラスを読み込むため、
テストコードのクラス名はTaskTest.phpなど、必ず末尾がTestになっている必要があります。

メソッド名

PHPUnitはtestで始まるメソッドを実行するため、
それに合わせてメソッド名を記載する必要があります。

public function testRegisterTask(): void
{
    // ...
}

もしくは、@testというアノテーションをメソッドのDocBlockに記述することで、
メソッド名がtestで始まらない場合でも、メソッドを実行できます。

/**
 * @test
 */
public function registerTask(): void
{
    // ...
}

構文

テスト時の最初と最後に実行されるメソッド

setUp()

setUp()は、各テストメソッドに対して最初に実行されるメソッドです。

例えば以下のように、認証が必要な場合のテストに有用なactingAsメソッドを実行し、
全てのテストメソッドでログイン状態を維持することができます。

    // テストメソッド毎に最初に実行される
    public function setup(): void
    {
        parent::setUp();
        
        // ユーザーデータを一つ作る
        $user = User::factory()->create();
        // ログインした状態にする
        $this->actingAs($user);
    }

tearDown()

反対に、tearDown()は各テストメソッドに対して最後に実行されます。

    // テストメソッド毎に最後に実行される
    protected function tearDown(): void
    {
        parent::tearDown();
    }

テストデータをリセット

RefreshDatabaseは、テスト開始時に一度だけデータベースをリセットし、
各メソッドで実行されたテストデータをリセット(ロールバック)します。

これを使用することで、各テストは独立して実行され
テストが他のテストメソッドに影響を与えずに行うことができます。

use Illuminate\Foundation\Testing\RefreshDatabase;
class TaskTest extends TestCase
{
	// テスト時にDBをリセット
	use RefreshDatabase;
	public function setup(): void
	{
	}
}

ステータスコード関連

以下はステータスコードをチェックする例です。

// 指定したステータスコードかどうか
$response->assertStatus(200);

// 200かどうか
$response->assertOk();

// 201かどうか
$response->assertCreated();

// 401かどうか
$response->assertUnauthorized();

// 403かどうか
$response->assertForbidden();

// 404かどうか
$response->assertNotFound();

// 422(validationエラー)かどうか
$response->assertUnprocessable();

データベース関連

データベースに関連するテストでは、特定のテーブルにデータが
正しく保存されているかなどを確認します。
以下は、データベース関連のアサーション例です。

// データベースに登録・更新された値が期待した通りかどうか
$this->assertDatabaseHas('tasks', [
    'title' => $title,
    'body' => $body,
]);

// テーブルに指定したデータが存在しないか
$this->assertDatabaseMissing('tasks', [
    'title' => 'not-existing-title',
]);

// データベースのレコード数が期待値と一致するか
$recordCount = DB::table('tasks')->count();
$this->assertDatabaseCount('tasks', $recordCount);

// データベースのレコードが指定数より多いかどうか
$this->assertTrue($recordCount > 5);

// データベースのレコードが指定数より少ないかどうか
$this->assertTrue($recordCount < 10);

参考

https://qiita.com/grohiro/items/4efc6c569be26e36aef2

Discussion