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