Jon Winstanley
Jon Winstanley

Reputation: 23311

Tests in Laravel - run database migrations just once per file, rather than for every individual test

In my Laravel application I have a large number of MySql tables and a large number of phpunit tests to run. I run tests in memory using Sqlite and have a series of Seeder files to add data to the test database.

For each test, Laravel creates a new database, runs the migrations and adds the data which takes a lot of time when multiplied by the number of tests.

I would like to specify that for some test files, the RefreshDatabase and DatabaseMigrations only needs to run once per file, not once per test.

Is that feature available in Laravel?

Upvotes: 2

Views: 3658

Answers (2)

Remul
Remul

Reputation: 8242

You could try the following:

use Illuminate\Foundation\Testing\DatabaseTransactions;

class YourTest extends TestCase
{
    use DatabaseTransactions;

    protected function setUp(): void
    {
        parent::setUp();

        $this->artisan('migrate');
    }

    /** @test */
    public function itDoesTheThing()
    {
        // code
    }
}

Here we use the DatabaseTransactions trait so everything we do inside the test will be wrapped inside transactions and rolled back after each test, then in the setUp method we migrate the database for each test, but it will only do it for the first test since the database will be migrated after the first test.

Another option would be to use a property that determines if you already migrated / seeded the database, something like this:

class YourTest extends TestCase
{
    use DatabaseTransactions;

    protected static $initialized = false;

    public function setUp(): void
    {
        parent::setUp();

        if (!self::$initialized) {
            // migrate and seed the database for each test only once

            self::$initialized = true;
        }
    }
}

Upvotes: 0

Mathieu Ferre
Mathieu Ferre

Reputation: 4412

If you don't want to refresh your migration for some test, put them in a Test class with this setup method:

protected function setUp(): void
{
    RefreshDatabaseState::$migrated = true; 

    parent::setUp();
}

RefreshDatabaseState::$migrated = true; will state to laravel that the migration already occure and don't have to be played again

Upvotes: 1

Related Questions