Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[9.x] Add DatabaseTruncation trait for testing #45726

Merged
merged 7 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions src/Illuminate/Foundation/Testing/DatabaseTruncation.php
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]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it will be better to use FQCN instead of the command name?

} 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')];
}
}
4 changes: 4 additions & 0 deletions src/Illuminate/Foundation/Testing/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ protected function setUpTraits()
$this->runDatabaseMigrations();
}

if (isset($uses[DatabaseTruncation::class])) {
$this->truncateDatabaseTables();
}

if (isset($uses[DatabaseTransactions::class])) {
$this->beginDatabaseTransaction();
}
Expand Down
1 change: 1 addition & 0 deletions src/Illuminate/Testing/Concerns/TestDatabases.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ protected function bootTestDatabase()
$databaseTraits = [
Testing\DatabaseMigrations::class,
Testing\DatabaseTransactions::class,
Testing\DatabaseTruncation::class,
Testing\RefreshDatabase::class,
];

Expand Down