Building a Database
Adapt creates and removes databases for your tests as needed. You don't need to create empty ones yourself beforehand.
Unless you choose otherwise, Adapt builds a database for your default
database connection.
Structure and Data
Adapt performs the following steps when building a database: Imports, Migrations and Seeders. Each step is optional.
Imports
You can tell Adapt to import custom database sql-dump file/s before your migrations and seeders run.
TIP
This is an alternative to Laravel's migration squashing feature, which you may want to use instead.
You can generate a sql-dump file using MySQL's mysqldump
command, or PostgreSQL's pg_dump
command.
To import your file, put it in your filesystem, and add it to Adapt's build_sources.initial_imports
config setting. You can also specify it per-test by adding the $initialImports
property to your test-classes.
⚙️ See configuration
<?php
// config/code_distortion.adapt.php
return [
…
'build_sources' => [
'initial_imports' => [
'mysql' => ['database/dumps/mysql/db.sql', …],
'pgsql' => ['database/dumps/pgsql/db.sql', …],
'sqlite' => ['database/dumps/sqlite/db.sqlite'], // NOTE: SQLite files are simply copied
],
…
],
…
];
or
<?php
// tests/Feature/MyFeatureTest.php
use CodeDistortion\Adapt\AdaptDatabase;
use Tests\TestCase;
class MyFeatureTest extends TestCase
{
use AdaptDatabase;
protected array $initialImports = [
'mysql' => ['database/dumps/mysql/db.sql', …],
'pgsql' => ['database/dumps/pgsql/db.sql', …],
'sqlite' => ['database/dumps/sqlite/db.sqlite'], // SQLite files are simply copied
];
…
}
Any remaining migrations will be run in the next step, after the import.
NOTE
SQLite database files aren't imported, they're simply copied, which is quite quick.
The imports feature isn't supported for SQLite :memory:
databases.
Migrations
Most likely you'll want your migrations to be run when building your database.
Migrations are turned on by default. You can turn them off by changing Adapt's build_sources.migrations
config setting, or by adding the $migrations
property to your test-classes.
Laravel's normal migration directory /database/migrations
is used by default, but you can specify another if you like.
⚙️ See configuration
<?php
// config/code_distortion.adapt.php
return [
…
'build_sources' => [
…
'migrations' => true, // or false
// or
// 'migrations' => 'path/to/migrations',
…
],
…
];
or
<?php
// tests/Feature/MyFeatureTest.php
use CodeDistortion\Adapt\AdaptDatabase;
use Tests\TestCase;
class MyFeatureTest extends TestCase
{
use AdaptDatabase;
protected bool|string $migrations = true; // or false
// or
// protected bool|string $migrations = 'path/to/migrations';
…
}
Adapt uses Laravel's normal migration functionality behind-the-scenes to run your migrations.
Seeders
Seeders can be used to populate the database with particular data, ready for your tests to use.
When Adapt runs your seeders (instead of you running them yourself within your tests), this data is included in Adapt's caching mechanisms. This saves them from needing to be run each time.
It's up to you about whether this is a good idea. If you build a custom set of test-data that's shared between your tests, those tests become reliant on that data. Any changes to this data may break your tests unexpectedly, including when adding new data.
If you have a common set of standard data that always needs to exist, this would be a good situation to use this in.
You can choose which seeder/s to run by setting the build_sources.seeders
config setting. You can also pick different seeders for different tests by adding the $seeders
property to your test-classes.
⚙️ See configuration
<?php
// config/code_distortion.adapt.php
return [
…
'build_sources' => [
…
'seeders' => 'SomeDatabaseSeeder', // or ''
// or
// 'seeders' => ['SomeDatabaseSeeder', 'SomeOtherDatabaseSeeder'], // or []
],
…
];
or
<?php
// tests/Feature/MyFeatureTest.php
use CodeDistortion\Adapt\AdaptDatabase;
use Tests\TestCase;
class MyFeatureTest extends TestCase
{
use AdaptDatabase;
protected string|array $seeders = 'SomeDatabaseSeeder'; // or ''
// or
// protected string|array $seeders = ['SomeDatabaseSeeder', 'SomeOtherDatabaseSeeder']; // or []
…
}
Adapt uses Laravel's normal seeder functionality behind-the-scenes to run your seeders.
Adapt will respect Laravel's $seed
and $seeder
properties if you happen to use them.
NOTE
Seeders are only run if initial-imports or migrations are enabled.
Building Extra Databases
If your project uses more than one database, Adapt can build them for your tests too.
To create more databases, add the databaseInit()
method to your test-class. Inside it, make a call to $this->prepareConnection($connection);
to prepare another database. You can do this for as many connections as you need.
Each call will give you a new DatabaseDefinition
object that you can configure. These are initially primed with your configuration settings.
A $database
parameter is passed to your databaseInit()
method. This is the DatabaseDefinition
object Adapt uses to build your default
connection's database.
⚙️ See configuration
<?php
// tests/Feature/MyFeatureTest.php
use CodeDistortion\Adapt\DatabaseDefinition;
use CodeDistortion\Adapt\AdaptDatabase;
use Tests\TestCase;
class MyFeatureTest extends TestCase
{
use AdaptDatabase;
protected function databaseInit(DatabaseDefinition $database): void
{
$initialImports = [
'mysql' => ['database/dumps/mysql/db.sql'],
'pgsql' => ['database/dumps/pgsql/db.sql'],
'sqlite' => ['database/dumps/sqlite/db.sqlite'], // SQLite files are simply copied
];
// the DatabaseDefinition $database is pre-configured to match your config settings
// for the "default" database connection
// you can override them with any of the following…
$database
->connection('primary') // specify another connection to build a db for
->initialImports($initialImports) // or ->noInitialImports()
->migrations() // or ->migrations('database/other_migrations') or ->noMigrations()
->seeders(['DatabaseSeeder']) // or ->noSeeders()
->isABrowserTest() // or ->isNotABrowserTest()
->transaction() // or ->noTransaction()
->journal() // or ->noJournal()
->snapshots('!afterSeeders') // or ->noSnapshots()
->remoteBuildUrl('https://...') // or ->noRemoteBuildUrl()
->forceRebuild() // or ->dontForceRebuild()
->makeDefault(); // make the "default" Laravel connection point to this connection
// you can create a database for another connection
$connection = 'secondary';
$database2 = $this->prepareConnection($connection);
$database2
->initialImports($initialImports); // or ->noInitialImports()
// etc …
}
…
}
// you can then use these database connections somewhere inside a test
DB::connection('primary')->select(…);
DB::connection('secondary')->select(…);
TIP
You might like to share your databaseInit()
method between tests by adding it to a trait or parent test-class.
Rebuilding Your Database
You don't need to rebuild your database when you update your migrations, seeders or factories. Adapt detects these changes, and rebuilds them automatically.
The directories listed in the cache_invalidation.locations
config setting are inspected for changes:
/database/migrations
/database/seeders
/database/factories
⚙️ See configuration
<?php
// config/code_distortion.adapt.php
return [
…
'cache_invalidation' => [
…
'locations' => [
database_path('migrations'),
database_path('seeders'), // Laravel 8 and after
// database_path('seeds'), // before Laravel 8
database_path('factories'),
// 'some/other/path',
],
…
],
…
];
TIP
If you add initial-imports, it would be a good idea to add these here as well. This way, changes to those will be detected as well.
After detecting changes, "old" databases will be marked as stale. These will be removed automatically after a little while.
Disabling Databases
You can tell Adapt to skip the database building process altogether. This might sound strange for a package whose purpose is to build databases. But it allows for other functionality to still be used.
You might wish to do this if your project doesn't have a database, and you'd still like to run your browser tests in parallel.
Database building is on by default. To turn it off, change Adapt's build_databases
config setting. Or you can add the $buildDatabases
property to your test-classes.
⚙️ See configuration
<?php
// config/code_distortion.adapt.php
return [
…
'build_databases' => true, // or false
…
];
or
<?php
// tests/Feature/MyFeatureTest.php
use CodeDistortion\Adapt\AdaptDatabase;
use Tests\TestCase;
class MyFeatureTest extends TestCase
{
use AdaptDatabase;
protected bool $buildDatabases = true; // or false
…
}