メインコンテンツまでスキップ

データベーステスト

はじめに

Laravel は、データベース駆動型のアプリケーションをテストするのを簡単にするためのさまざまな便利なツールやアサーションを提供しています。さらに、Laravel のモデルファクトリとシーダを使用すると、アプリケーションの Eloquent モデルとリレーションシップを使用してテストデータベースレコードを簡単に作成できます。これらの強力な機能について、以下のドキュメントで詳しく説明します。

各テスト後にデータベースをリセットする

さらに進む前に、前のテストのデータが後続のテストに干渉しないように、各テスト後にデータベースをリセットする方法について説明しましょう。Laravel には、Illuminate\Foundation\Testing\RefreshDatabase トレイトが含まれており、これを使用するとデータベースをリセットできます。単純にテストクラスでこのトレイトを使用します:

<?php

use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

test('basic example', function () {
$response = $this->get('/');

// ...
});
<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ExampleTest extends TestCase
{
use RefreshDatabase;

/**
* A basic functional test example.
*/
public function test_basic_example(): void
{
$response = $this->get('/');

// ...
}
}

Illuminate\Foundation\Testing\RefreshDatabase トレイトは、スキーマが最新である場合にデータベースをマイグレートしません。代わりに、データベーストランザクション内でテストを実行します。したがって、このトレイトを使用しないテストケースでデータベースに追加されたレコードはまだ存在する可能性があります。

データベースを完全にリセットしたい場合は、Illuminate\Foundation\Testing\DatabaseMigrations または Illuminate\Foundation\Testing\DatabaseTruncation トレイトを代わりに使用できます。ただし、これらのオプションは RefreshDatabase トレイトよりもかなり遅くなります。

モデルファクトリ

テスト時に、テストを実行する前にデータベースにいくつかのレコードを挿入する必要がある場合があります。このテストデータを作成する際に各列の値を手動で指定する代わりに、Laravel では、モデルファクトリを使用して、各 Eloquent モデル のデフォルト属性セットを定義できます。

モデルファクトリを作成して利用する方法について詳しく学ぶには、完全なmodel factory documentationを参照してください。モデルファクトリを定義したら、テスト内でモデルを作成するためにファクトリを利用できます:

use App\Models\User;

test('models can be instantiated', function () {
$user = User::factory()->create();

// ...
});
use App\Models\User;

public function test_models_can_be_instantiated(): void
{
$user = User::factory()->create();

// ...
}

シーダの実行

機能テスト中にデータベースをポピュレートするためにデータベースシーダを使用したい場合は、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 () {
// Run the DatabaseSeeder...
$this->seed();

// Run a specific seeder...
$this->seed(OrderStatusSeeder::class);

// ...

// Run an array of specific seeders...
$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;

/**
* Test creating a new order.
*/
public function test_orders_can_be_created(): void
{
// Run the DatabaseSeeder...
$this->seed();

// Run a specific seeder...
$this->seed(OrderStatusSeeder::class);

// ...

// Run an array of specific seeders...
$this->seed([
OrderStatusSeeder::class,
TransactionStatusSeeder::class,
// ...
]);
}
}

また、RefreshDatabaseトレイトを使用する各テストの前にデータベースを自動的にシードするようにLaravelに指示することもできます。これは、ベーステストクラスで$seedプロパティを定義することで実現できます:

    <?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
/**
* Indicates whether the default seeder should run before each test.
*
* @var bool
*/
protected $seed = true;
}

$seedプロパティがtrueの場合、テストはRefreshDatabaseトレイトを使用する各テストの前にDatabase\Seeders\DatabaseSeederクラスを実行します。ただし、テストクラスで$seederプロパティを定義することで、実行する特定のシーダを指定することもできます:

    use Database\Seeders\OrderStatusSeeder;

/**
* Run a specific seeder before each test.
*
* @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);

<a name="assert-not-deleted"></a>

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);

// テスト...