コンテンツにスキップ

データベーステスト

はじめに

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モデルごとにデフォルトの属性セットをモデルファクトリを使用して定義できます。

モデルの作成にモデルファクトリを作成および活用する方法の詳細については、モデルファクトリのドキュメント全体を参照してください。モデルファクトリを定義したら、テスト内でファクトリを利用してモデルを作成できます。

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

assertDatabaseEmpty

データベース内のテーブルにレコードが含まれていないことをアサートします。

$this->assertDatabaseEmpty('users');

assertDatabaseHas

データベース内のテーブルに、指定されたキー/値のクエリ制約に一致するレコードが含まれていることをアサートします。

$this->assertDatabaseHas('users', [
'email' => '[email protected]',
]);

assertDatabaseMissing

データベース内のテーブルに、指定されたキー/値のクエリ制約に一致するレコードが含まれていないことをアサートします。

$this->assertDatabaseMissing('users', [
'email' => '[email protected]',
]);

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);
 
// Test...