-
Notifications
You must be signed in to change notification settings - Fork 11.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[9.x] Add
DatabaseTruncates
trait for testing (#45726)
* Add DatabaseTruncates option for setting up DB Migrate the database in the first run, then truncate the affected tables and use the seeder for subsequent runs. * Use a specific seeder if it's set, otherwise use the default * use migrations table from config * Handle truncating multiple connections * allow excluding tables per connection * unset the event dispatcher before truncating, re-set afterwards * Get the database ready at the start of the test * This removes potential conflicts with other beforeApplicationDestroyed callbacks, where a database is needed * This matches the behaviour of the other tests instead of removing data afterwards. * It also makes it easier to check the data after failed tests, especially when a dusk test fails. * useForeignKeyChecks * allow the developer to specify which connections use foreign key checks, default to all connections * allwo the developer to create an excludeTables property instead of having to override the method * formatting --------- Co-authored-by: Taylor Otwell <taylor@laravel.com>
- Loading branch information
1 parent
33c0324
commit 5273fac
Showing
3 changed files
with
123 additions
and
0 deletions.
There are no files selected for viewing
118 changes: 118 additions & 0 deletions
118
src/Illuminate/Foundation/Testing/DatabaseTruncation.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
<?php | ||
|
||
namespace Illuminate\Foundation\Testing; | ||
|
||
use Illuminate\Contracts\Console\Kernel; | ||
use Illuminate\Database\ConnectionInterface; | ||
use Illuminate\Foundation\Testing\Traits\CanConfigureMigrationCommands; | ||
|
||
trait DatabaseTruncation | ||
{ | ||
use CanConfigureMigrationCommands; | ||
|
||
/** | ||
* The cached names of the database tables for each connection. | ||
* | ||
* @var array | ||
*/ | ||
protected static array $allTables; | ||
|
||
/** | ||
* Truncate the database tables for all configured connections. | ||
* | ||
* @return void | ||
*/ | ||
protected function truncateDatabaseTables(): void | ||
{ | ||
// Migrate and seed the database on first run... | ||
if (! RefreshDatabaseState::$migrated) { | ||
$this->artisan('migrate:fresh', $this->migrateFreshUsing()); | ||
|
||
$this->app[Kernel::class]->setArtisan(null); | ||
|
||
RefreshDatabaseState::$migrated = true; | ||
|
||
return; | ||
} | ||
|
||
// Always clear any test data on subsequent runs... | ||
$this->truncateTablesForAllConnections(); | ||
|
||
if ($seeder = $this->seeder()) { | ||
// Use a specific seeder class... | ||
$this->artisan('db:seed', ['--class' => $seeder]); | ||
} elseif ($this->shouldSeed()) { | ||
// Use the default seeder class... | ||
$this->artisan('db:seed'); | ||
} | ||
} | ||
|
||
/** | ||
* Truncate the database tables for all configured connections. | ||
* | ||
* @return void | ||
*/ | ||
protected function truncateTablesForAllConnections(): void | ||
{ | ||
$database = $this->app->make('db'); | ||
|
||
collect($this->connectionsToTruncate()) | ||
->each(function ($name) use ($database) { | ||
$connection = $database->connection($name); | ||
|
||
$connection->getSchemaBuilder()->withoutForeignKeyConstraints( | ||
fn () => $this->truncateTablesForConnection($connection, $name) | ||
); | ||
}); | ||
} | ||
|
||
/** | ||
* Truncate the database tables for the given database connection. | ||
* | ||
* @param \Illuminate\Database\ConnectionInterface $connection | ||
* @param string|null $name | ||
* @return void | ||
*/ | ||
protected function truncateTablesForConnection(ConnectionInterface $connection, ?string $name): void | ||
{ | ||
$dispatcher = $connection->getEventDispatcher(); | ||
|
||
$connection->unsetEventDispatcher(); | ||
|
||
collect(static::$allTables[$name] ??= $connection->getDoctrineSchemaManager()->listTableNames()) | ||
->diff($this->exceptTables($name)) | ||
->filter(fn ($table) => $connection->table($table)->exists()) | ||
->each(fn ($table) => $connection->table($table)->truncate()); | ||
|
||
$connection->setEventDispatcher($dispatcher); | ||
} | ||
|
||
/** | ||
* The database connections that should have their tables truncated. | ||
* | ||
* @return array | ||
*/ | ||
protected function connectionsToTruncate(): array | ||
{ | ||
return property_exists($this, 'connectionsToTruncate') | ||
? $this->connectionsToTruncate : [null]; | ||
} | ||
|
||
/** | ||
* Get the tables that should not be truncated. | ||
* | ||
* @param string|null $connectionName | ||
* @return array | ||
*/ | ||
protected function exceptTables(?string $connectionName): array | ||
{ | ||
if (property_exists($this, 'exceptTables')) { | ||
return array_merge( | ||
$this->exceptTables[$connectionName] ?? [], | ||
[$this->app['config']->get('database.migrations')] | ||
); | ||
} | ||
|
||
return [$this->app['config']->get('database.migrations')]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters