How to speed up Laravel Unit tests using Schema:Dump

Laravel, an open-source PHP framework, provides built-in functionalities for developers to write tests for their applications. However, running tests, especially database tests, can sometimes be slow and time-consuming, affecting the productivity of developers. This blog post will elaborate on how to speed up Laravel unit tests using the schema::dump command.

The Problem

While performing unit tests in Laravel, developers often face a problem: migrations. Each time you run a test, Laravel runs all migrations, creating a database schema. If your application has a lot of migration files, the process of migrating them every time can be quite slow. This can be a significant slowdown when running a large number of tests, resulting in a longer time taken to conduct the tests.

The Solution

To resolve this, Laravel introduced an artisan command, schema::dump, in Laravel 8.x, which generates a schema file from your migrations. It dumps the database schema into a SQL file, which can then be run instead of the individual migrations. This significantly speeds up the execution of tests.

Here's how you can implement it:

Step 1: Create a Schema Dump

Firstly, you need to create a schema dump. Before running dump command make sure you migrate your existing migrations to DB:

php artisan migrate

You can do this by running the following Artisan command:

php artisan schema:dump

This will create a file called mysql-schema.dump inside your database/schema directory. This file will contain all the SQL necessary to create your database schema based on your current mysql database.

Step 2: Configure PHPUnit

Next, you need to tell PHPUnit to use the schema dump instead of running all migrations. Open your phpunit.xml file and add the following lines:

<env name="DB_CONNECTION" value="mysql"/>
<env name="DB_DATABASE" value="mydb"/>
<env name="USE_SCHEMA_DUMP" value="true"/>

The USE_SCHEMA_DUMP environment variable will tell Laravel to use the schema dump instead of the migrations.

Step 3: Update Your CreatesApplication Trait

The CreatesApplication trait is used by Laravel to set up the testing environment. You need to modify it to check for the USE_SCHEMA_DUMP environment variable and load the schema dump if it's set.

Open the CreatesApplication trait located in tests/CreatesApplication.php and update the createApplication method:

public function createApplication()
{
    $app = require __DIR__.'/../bootstrap/app.php';

    $app->make(Kernel::class)->bootstrap();

    // check if we should use the schema dump
    if (env('USE_SCHEMA_DUMP')) {
        $this->loadSchemaDump();
    } else {
        $this->runDatabaseMigrations();
    }

    return $app;
}

protected function loadSchemaDump()
{
    // turn off foreign key checks
    DB::statement('SET FOREIGN_KEY_CHECKS=0;');

    // get all table names
    $tables = DB::select('SHOW TABLES');

    // drop all tables
    foreach ($tables as $table) {
        // TODO Replace 'mydb' with your database name
        $tableName = $table->Tables_in_mydb;
        DB::statement("DROP TABLE {$tableName}");
    }

    // turn foreign key checks back on
    DB::statement('SET FOREIGN_KEY_CHECKS=1;');

    // load the schema dump
    DB::unprepared(file_get_contents(database_path('schema/mysql-schema.dump')));
}

protected function runDatabaseMigrations()
{
    $this->artisan('migrate');
}

This code will check if the USE_SCHEMA_DUMP environment variable is set. If it is, it will load the schema dump; otherwise, it will run the migrations.

Conclusion

Using Schema::dump can significantly speed up your Laravel unit tests, especially if you have a lot of migrations. It allows you to dump your database schema into a SQL file and use that file instead of the individual migrations. This can save you a ot of time and help improve your productivity.

However, please remember that while the use of schema::dump is great for speeding up tests, you should be careful when using it in a production environment. It's important to remember that the schema dump file represents the current database schema at the point when the dump was created. Therefore, if you make changes to your migrations, you need to remember run those migrations and then create a new schema dump. Otherwise, your tests could be running against an outdated schema.

As with any tool, it's essential to understand how and when to use it. schema::dump is a powerful tool, but it isn't always the right solution. For example, if your application has a few migrations, or if your migrations change often, using the traditional migration system might be simpler and more efficient.

In conclusion, Laravel's Schema::dump can be an excellent tool for speeding up your unit tests. By reducing the time by almost 80 - 90% it takes to set up the test database, you can spend more time writing and refining your tests. This can help you catch bugs earlier, improve the quality of your code, and deliver a better product to your users. Happy testing!

Leave a Reply

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.