#はじめに
Laravel は、データベース駆動のアプリケーションをテストしやすくするための便利なツールやアサーションを多数提供しています。さらに、Laravel のモデルファクトリーとシーダーを使うことで、Eloquent モデルやリレーションシップを利用してテスト用のデータベースレコードを簡単に作成できます。以下のドキュメントでこれらの強力な機能について説明します。
#各テスト後のデータベースリセット
次に進む前に、各テスト後にデータベースをリセットして、前のテストのデータが後続のテストに影響しないようにする方法を説明します。Laravel に含まれる Illuminate\Foundation\Testing\RefreshDatabase トレイトがこれを自動で処理します。テストクラスでこのトレイトを使うだけです:
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
use RefreshDatabase;
/**
* 基本的な機能テストの例です。
*/
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;
public function test_models_can_be_instantiated(): void
{
$user = User::factory()->create();
// ...
}
#シーダーの実行
機能テストの実行中にデータベースにデータを投入するためにデータベースシーダーを使用する場合は、seed メソッドを呼び出せます。デフォルトでは、seed メソッドは DatabaseSeeder を実行し、DatabaseSeeder が他のすべてのシーダーを実行します。あるいは、特定のシーダークラス名を seed メソッドに渡すこともできます:
<?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
{
use CreatesApplication;
/**
* 各テストの前にデフォルトのシーダーを実行するかどうかを示します。
*
* @var bool
*/
protected $seed = true;
}
$seed プロパティが true の場合、RefreshDatabase トレイトを使う各テストの前に Database\Seeders\DatabaseSeeder クラスが実行されます。ただし、特定のシーダーを実行したい場合は、テストクラスに $seeder プロパティを定義してください:
use Database\Seeders\OrderStatusSeeder;
/**
* 各テストの前に特定のシーダーを実行します。
*
* @var string
*/
protected $seeder = OrderStatusSeeder::class;
#利用可能なアサーション
Laravel は PHPUnit の機能テスト用にいくつかのデータベースアサーションを提供しています。以下でそれぞれのアサーションについて説明します。
#assertDatabaseCount
指定したテーブルに指定した数のレコードが存在することをアサートします:
$this->assertDatabaseCount('users', 5);
#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);
// テスト...