Laravelのデータベーステスト時に予めデータ投入しておきたい時のtipsです。
各テストに依存するシーダーは各シーダーで実行するのが良いと思いますが、マスターデータ等システム全般で使用するものはテスト前に実行しておきたいです。
事前情報
tests/TestCase.php
はLaravelが元々用意してくれているファイルです。
TestCase
を継承して各テストクラスを作っていきます。
<?php
declare(strict_types=1);
namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
}
phpunit.xml
でテスト用のDockerコンテナを指定してます。
<php>
<env name="DB_CONNECTION" value="mysql"/>
<env name="DB_HOST" value="db-testing"/>
</php>
手順
tests/TestCase.php
下記のように書き換えます。
<?php
declare(strict_types=1);
namespace Tests;
use Database\Seeders\TestingDatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
use RefreshDatabase;
protected string $seeder = TestingDatabaseSeeder::class;
}
$seeder
には1つのシーダーを指定できます。
今後複数のシーダーを呼び出すことを考慮してテスト用のシーダークラスを作ります。
$ php artisan make:seeder TestingDatabaseSeeder
<?php
declare(strict_types=1);
namespace Database\Seeders;
use Illuminate\Database\Seeder;
final class TestingDatabaseSeeder extends Seeder
{
/**
* @return void
*/
public function run(): void
{
$this->call([
RolesAndPermissionsSeeder::class,
]);
}
}
$this->call()
関数にテスト時に実行したいシーダークラスを指定します。
補足
RefreshDatabase
トレイトが用意されています。
trait RefreshDatabase
{
use CanConfigureMigrationCommands;
}
trait CanConfigureMigrationCommands
{
/**
* Determine the specific seeder class that should be used when refreshing the database.
*
* @return mixed
*/
protected function seeder()
{
return property_exists($this, 'seeder') ? $this->seeder : false;
}
}
seeder
プロパティにシーダークラスを指定するとデータベースリフレッシュ時にシーダーを実行してくれます。
RefreshDatabase
トレイトはマイグレーションスキーマが最新であればデータベースをマイグレートしません。(初回のみ実行される)
2回目以降はデータベーストランザクション内でテストが実行されるので、TestingDatabaseSeeder
だけ実行されたクリーンな状態でテストが実行されていきます。
参考