LoginSignup
6
0

More than 1 year has passed since last update.

Laravel テスト用のシーダーを初回のみ実行する

Last updated at Posted at 2022-09-21

Laravelのデータベーステスト時に予めデータ投入しておきたい時のtipsです。
各テストに依存するシーダーは各シーダーで実行するのが良いと思いますが、マスターデータ等システム全般で使用するものはテスト前に実行しておきたいです。

事前情報

tests/TestCase.php はLaravelが元々用意してくれているファイルです。
TestCase を継承して各テストクラスを作っていきます。

tests/TestCase.php
<?php

declare(strict_types=1);

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;
}

phpunit.xml でテスト用のDockerコンテナを指定してます。

phpunit.xml
    <php>
        <env name="DB_CONNECTION" value="mysql"/>
        <env name="DB_HOST" value="db-testing"/>
    </php>

手順

tests/TestCase.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
database/seeders/TestingDatabaseSeeder.php
<?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 トレイトが用意されています。

vendor/laravel/framework/src/Illuminate/Foundation/Testing/RefreshDatabase.php
trait RefreshDatabase
{
    use CanConfigureMigrationCommands;
}
vendor/laravel/framework/src/Illuminate/Foundation/Testing/Traits/CanConfigureMigrationCommands.php
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だけ実行されたクリーンな状態でテストが実行されていきます。

参考

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0