データベーステスト¶
イントロダクション¶
Laravelは、データベース駆動のアプリケーションを簡単にテストできるように、さまざまな便利なツールとアサーションを提供しています。さらに、Laravelのモデルファクトリとシーダーを使用すると、アプリケーションのEloquentモデルとリレーションを使用して、テストデータベースレコードを簡単に作成できます。これらの強力な機能については、以下のドキュメントで説明します。
各テスト後のデータベースリセット¶
さらに進む前に、各テスト後にデータベースをリセットする方法について説明しましょう。これにより、前のテストのデータが後続のテストに干渉しないようになります。Laravelに含まれるIlluminate\Foundation\Testing\RefreshDatabaseトレイトが、これを処理します。テストクラスでトレイトを使用するだけです:
Illuminate\Foundation\Testing\RefreshDatabaseトレイトは、スキーマが最新の場合、データベースをマイグレートしません。代わりに、データベーストランザクション内でテストを実行するだけです。したがって、このトレイトを使用しないテストケースによってデータベースに追加されたレコードは、データベースに残る可能性があります。
データベースを完全にリセットしたい場合は、代わりにIlluminate\Foundation\Testing\DatabaseMigrationsまたはIlluminate\Foundation\Testing\DatabaseTruncationトレイトを使用できます。ただし、これらのオプションはRefreshDatabaseトレイトよりも大幅に遅くなります。
モデルファクトリ¶
テストを行う際、テストを実行する前にデータベースにいくつかのレコードを挿入する必要があるかもしれません。このテストデータを作成する際に、各列の値を手動で指定する代わりに、Laravelではモデルファクトリを使用して、各Eloquentモデルのデフォルト属性のセットを定義できます。
モデルファクトリの作成と使用方法について詳しくは、完全なモデルファクトリのドキュメントを参照してください。モデルファクトリを定義したら、テスト内でファクトリを使用してモデルを作成できます:
シーダーの実行¶
機能テスト中にデータベースシーダーを使用してデータベースをデータで埋めたい場合は、seedメソッドを呼び出すことができます。デフォルトでは、seedメソッドはDatabaseSeederを実行し、これにより他のすべてのシーダーが実行されます。または、特定のシーダークラス名をseedメソッドに渡すこともできます:
<?php
use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
test('orders can be created', function () {
    // DatabaseSeederを実行...
    $this->seed();
    // 特定のシーダーを実行...
    $this->seed(OrderStatusSeeder::class);
    // ...
    // 特定のシーダーの配列を実行...
    $this->seed([
        OrderStatusSeeder::class,
        TransactionStatusSeeder::class,
        // ...
    ]);
});
<?php
namespace Tests\Feature;
use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
    use RefreshDatabase;
    /**
     * 新しい注文の作成テスト。
     */
    public function test_orders_can_be_created(): void
    {
        // DatabaseSeederを実行...
        $this->seed();
        // 特定のシーダーを実行...
        $this->seed(OrderStatusSeeder::class);
        // ...
        // 特定のシーダーの配列を実行...
        $this->seed([
            OrderStatusSeeder::class,
            TransactionStatusSeeder::class,
            // ...
        ]);
    }
}
または、RefreshDatabaseトレイトを使用する各テストの前に、Laravelにデータベースを自動的にシードするように指示できます。これは、ベーステストクラスに$seedプロパティを定義することで実現できます:
<?php
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
    /**
     * 各テストの前にデフォルトのシーダーを実行するかどうかを示します。
     *
     * @var bool
     */
    protected $seed = true;
}
$seedプロパティがtrueの場合、RefreshDatabaseトレイトを使用する各テストの前にDatabase\Seeders\DatabaseSeederクラスが実行されます。ただし、テストクラスに$seederプロパティを定義することで、特定のシーダーを実行するように指定できます:
use Database\Seeders\OrderStatusSeeder;
/**
 * 各テストの前に実行する特定のシーダー。
 *
 * @var string
 */
protected $seeder = OrderStatusSeeder::class;
利用可能なアサーション¶
Laravelは、PestまたはPHPUnitの機能テスト用にいくつかのデータベースアサーションを提供しています。以下では、これらの各アサーションについて説明します。
assertDatabaseCount¶
データベース内のテーブルに指定された数のレコードが含まれていることをアサートします:
$this->assertDatabaseCount('users', 5);
assertDatabaseHas¶
データベース内のテーブルに、指定されたキー/値のクエリ制約に一致するレコードが含まれていることをアサートします:
$this->assertDatabaseHas('users', [
    'email' => 'sally@example.com',
]);
assertDatabaseMissing¶
データベース内のテーブルに、指定されたキー/値のクエリ制約に一致するレコードが含まれていないことをアサートします:
$this->assertDatabaseMissing('users', [
    'email' => 'sally@example.com',
]);
assertSoftDeleted¶
assertSoftDeletedメソッドは、指定されたEloquentモデルが「ソフトデリート」されたことをアサートするために使用できます:
$this->assertSoftDeleted($user);
assertNotSoftDeleted¶
assertNotSoftDeletedメソッドは、指定されたEloquentモデルが「ソフトデリート」されていないことをアサートするために使用できます:
$this->assertNotSoftDeleted($user);
assertModelExists¶
指定されたモデルがデータベースに存在することをアサートします:
use App\Models\User;
$user = User::factory()->create();
$this->assertModelExists($user);
assertModelMissing¶
指定されたモデルがデータベースに存在しないことをアサートします:
use App\Models\User;
$user = User::factory()->create();
$user->delete();
$this->assertModelMissing($user);
expectsDatabaseQueryCount¶
expectsDatabaseQueryCountメソッドは、テストの開始時に呼び出され、テスト中に実行されるデータベースクエリの総数を指定できます。実際のクエリ数がこの期待値と一致しない場合、テストは失敗します:
$this->expectsDatabaseQueryCount(5);
// テスト...