Pest Plugin Database Migrations
Load a package's migrations in tests in the exact order declared by its spatie/laravel-package-tools ServiceProvider
#Pest Plugin Database Migrations
Load a Laravel package's migrations in your tests in the exact order declared by its
ServiceProvider. The provider's hasMigrations() list is the truth; the test suite just
reads it.
Packages built with spatie/laravel-package-tools
ship migrations without timestamps, usually as .php.stub, and declare the run order in the
provider:
$package->hasMigrations([ 'create_kb_categories_table', 'create_kb_articles_table', 'create_kb_article_versions_table', 'create_kb_article_feedback_table', 'create_kb_article_relations_table', 'add_kb_content_localization', 'add_kb_collections', ]);
Laravel's migrator ignores that order and sorts files by name. create_kb_article_versions_table
sorts before create_kb_articles_table (_ < s in ASCII), which sorts before
create_kb_categories_table it references. SQLite doesn't enforce foreign keys at
CREATE TABLE time, so the suite passes locally, then breaks on MySQL/PostgreSQL. The usual
fixes are all bad: copying stubs around in defineDatabaseMigrations(), or keeping a second,
hand-maintained list of migration names in TestCase that drifts every time the package gains
a migration. This package reads the list straight from the ServiceProvider, so there is
nothing to keep in sync.
#Installation
You can install the package via composer:
composer require jeffersongoncalves/pest-plugin-database-migrations --dev
#Usage
#Orchestra Testbench
// tests/TestCase.php use Illuminate\Foundation\Testing\RefreshDatabase; use JeffersonGoncalves\KnowledgeBase\KnowledgeBaseServiceProvider; use JeffersonGoncalves\PestPluginDatabaseMigrations\LoadsPackageMigrations; use Orchestra\Testbench\TestCase as Orchestra; abstract class TestCase extends Orchestra { use LoadsPackageMigrations; use RefreshDatabase; protected function defineDatabaseMigrations(): void { $this->loadPackageMigrations(KnowledgeBaseServiceProvider::class); } }
// tests/Pest.php uses(Tests\TestCase::class)->in('Feature', 'Unit');
#Before / after
What it replaces:
protected function defineDatabaseMigrations(): void { $migrationsPath = __DIR__.'/../vendor/jeffersongoncalves/laravel-knowledge-base/database/migrations'; if (is_dir($migrationsPath)) { foreach (glob($migrationsPath.'/*.php.stub') as $stub) { $migrationPath = str_replace('.php.stub', '.php', $stub); if (! file_exists($migrationPath)) { copy($stub, $migrationPath); } } $this->loadMigrationsFrom($migrationsPath); } }
protected function defineDatabaseMigrations(): void { $this->loadPackageMigrations(KnowledgeBaseServiceProvider::class); }
It works the same for a package's own test suite and for an app or package testing against a
dependency installed in vendor/ — the provider class is all it needs.
#Multiple packages
Providers are loaded in the order you pass them, so a package can be migrated after the one it depends on:
$this->loadPackageMigrations( BaseServiceProvider::class, ExtensionServiceProvider::class, );
#Without the trait
use JeffersonGoncalves\PestPluginDatabaseMigrations\PackageMigrations; // Ordered absolute paths of the declared migration files. PackageMigrations::files($app, KnowledgeBaseServiceProvider::class); // Stages them in a temp directory and returns it, ready for loadMigrationsFrom(). PackageMigrations::stage($app, KnowledgeBaseServiceProvider::class);
#How it works
- Instantiates the provider and calls
configurePackage()to readmigrationFileNames— nothing is registered or booted. - Resolves each name to
database/migrations/{name}.php, falling back to{name}.php.stub, the same waylaravel-package-toolsdoes. - Copies them to
sys_get_temp_dir()/pest-plugin-database-migrations/<hash>/as0000_name.php,0001_name.php, … and hands that directory toloadMigrationsFrom(). Files are only rewritten when their content changes, so parallel test workers don't read half-written files, and leftovers from a previous order are removed.
A declared migration that can't be found throws a RuntimeException naming the migration
and the provider, instead of silently skipping it.
#Known limitations
- Only
spatie/laravel-package-toolsproviders. The provider must extendSpatie\LaravelPackageTools\PackageServiceProviderand declare migrations withhasMigration()/hasMigrations(). discoversMigrations()is not supported. Discovered migrations have no declared order to read; load that directory withloadMigrationsFrom()directly.- Migration names in the
migrationstable get the numeric prefix (0001_create_kb_articles_table). Only relevant if a test asserts on those names.
#Testing
composer test
#Changelog
Please see CHANGELOG for more information on what has changed recently.
#Security
If you discover any security related issues, please email the author instead of using the issue tracker.
#Credits
#License
The MIT License (MIT). Please see License File for more information.