Skip to content

Commit

Permalink
Merge pull request #3993 from kenjis/feat-database-testing-setup
Browse files Browse the repository at this point in the history
feat: make migration/seed settings flexible on database testing
  • Loading branch information
MGatner authored Jan 5, 2021
2 parents 479b296 + 91fd266 commit 51d4611
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 22 deletions.
130 changes: 112 additions & 18 deletions system/Test/CIDatabaseTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,42 @@
abstract class CIDatabaseTestCase extends CIUnitTestCase
{
/**
* Should the db be refreshed before
* each test?
* Should run db migration?
*
* @var boolean
*/
protected $migrate = true;

/**
* Should run db migration only once?
*
* @var boolean
*/
protected $migrateOnce = false;

/**
* Is db migration done once or more than once?
*
* @var boolean
*/
private static $doneMigration = false;

/**
* Should run seeding only once?
*
* @var boolean
*/
protected $seedOnce = false;

/**
* Is seeding done once or more than once?
*
* @var boolean
*/
private static $doneSeed = false;

/**
* Should the db be refreshed before test?
*
* @var boolean
*/
Expand Down Expand Up @@ -139,28 +173,41 @@ protected function setUp(): void

$this->loadDependencies();

if ($this->refresh === true)
{
$this->regressDatabase();

// Reset counts on faked items
Fabricator::resetCounts();
}
$this->setUpMigrate();
$this->setUpSeed();
}

$this->migrateDatabase();
//--------------------------------------------------------------------

if (! empty($this->seed))
/**
* Migrate on setUp
*/
protected function setUpMigrate()
{
if ($this->migrateOnce === false || self::$doneMigration === false)
{
if (! empty($this->basePath))
if ($this->refresh === true)
{
$this->seeder->setPath(rtrim($this->basePath, '/') . '/Seeds');
}
$this->regressDatabase();

$seeds = is_array($this->seed) ? $this->seed : [$this->seed];
foreach ($seeds as $seed)
{
$this->seed($seed);
// Reset counts on faked items
Fabricator::resetCounts();
}

$this->migrateDatabase();
}
}

//--------------------------------------------------------------------

/**
* Seed on setUp
*/
protected function setUpSeed()
{
if ($this->seedOnce === false || self::$doneSeed === false)
{
$this->runSeeds();
}
}

Expand All @@ -187,11 +234,40 @@ protected function tearDown(): void

//--------------------------------------------------------------------

/**
* Run seeds as defined by the class
*/
protected function runSeeds()
{
if (! empty($this->seed))
{
if (! empty($this->basePath))
{
$this->seeder->setPath(rtrim($this->basePath, '/') . '/Seeds');
}

$seeds = is_array($this->seed) ? $this->seed : [$this->seed];
foreach ($seeds as $seed)
{
$this->seed($seed);
}
}

self::$doneSeed = true;
}

//--------------------------------------------------------------------

/**
* Regress migrations as defined by the class
*/
protected function regressDatabase()
{
if ($this->migrate === false)
{
return;
}

// If no namespace was specified then rollback all
if (empty($this->namespace))
{
Expand All @@ -217,11 +293,17 @@ protected function regressDatabase()
*/
protected function migrateDatabase()
{
if ($this->migrate === false)
{
return;
}

// If no namespace was specified then migrate all
if (empty($this->namespace))
{
$this->migrations->setNamespace(null);
$this->migrations->latest('tests');
self::$doneMigration = true;
}
// Run migrations for each specified namespace
else
Expand All @@ -232,6 +314,7 @@ protected function migrateDatabase()
{
$this->migrations->setNamespace($namespace);
$this->migrations->latest('tests');
self::$doneMigration = true;
}
}
}
Expand Down Expand Up @@ -361,4 +444,15 @@ public function seeNumRecords(int $expected, string $table, array $where)
}

//--------------------------------------------------------------------

/**
* Reset $doneMigration and $doneSeed
*
* @afterClass
*/
public static function resetMigrationSeedCount()
{
self::$doneMigration = false;
self::$doneSeed = false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php namespace CodeIgniter\Database\DatabaseTestCase;

use CodeIgniter\Test\CIDatabaseTestCase;
use Config\Database;
use Config\Services;

/**
* DatabaseTestCaseMigrationOnce1Test and DatabaseTestCaseMigrationOnce2Test
* show $migrateOnce applies per test case file.
*
* @group DatabaseLive
*/
class DatabaseTestCaseMigrationOnce1Test extends CIDatabaseTestCase
{
/**
* Should run db migration only once?
*
* @var boolean
*/
protected $migrateOnce = true;

/**
* Should the db be refreshed before test?
*
* @var boolean
*/
protected $refresh = true;

/**
* The namespace(s) to help us find the migration classes.
* Empty is equivalent to running `spark migrate -all`.
* Note that running "all" runs migrations in date order,
* but specifying namespaces runs them in namespace order (then date)
*
* @var string|array|null
*/
protected $namespace = [
'Tests\Support\MigrationTestMigrations',
];

public function setUp(): void
{
Services::autoloader()->addNamespace('Tests\Support\MigrationTestMigrations', SUPPORTPATH . 'MigrationTestMigrations');

parent::setUp();
}

public function testMigrationDone()
{
$this->seeInDatabase('foo', ['key' => 'foobar']);

// Drop table to make sure there is no foo table when
// DatabaseTestCaseMigrationOnce2Test runs
$this->dropTableFoo();
}

private function dropTableFoo()
{
$forge = Database::forge();
$forge->dropTable('foo', true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php namespace CodeIgniter\Database\DatabaseTestCase;

use CodeIgniter\Test\CIDatabaseTestCase;
use Config\Services;

/**
* DatabaseTestCaseMigrationOnce1Test and DatabaseTestCaseMigrationOnce2Test
* show $migrateOnce applies per test case file.
*
* @group DatabaseLive
*/
class DatabaseTestCaseMigrationOnce2Test extends CIDatabaseTestCase
{
/**
* Should run db migration only once?
*
* @var boolean
*/
protected $migrateOnce = true;

/**
* Should the db be refreshed before test?
*
* @var boolean
*/
protected $refresh = true;

/**
* The namespace(s) to help us find the migration classes.
* Empty is equivalent to running `spark migrate -all`.
* Note that running "all" runs migrations in date order,
* but specifying namespaces runs them in namespace order (then date)
*
* @var string|array|null
*/
protected $namespace = [
'Tests\Support\MigrationTestMigrations',
];

public function setUp(): void
{
Services::autoloader()->addNamespace('Tests\Support\MigrationTestMigrations', SUPPORTPATH . 'MigrationTestMigrations');

parent::setUp();
}

public function testMigrationDone()
{
$this->seeInDatabase('foo', ['key' => 'foobar']);
}
}
25 changes: 21 additions & 4 deletions user_guide_src/source/testing/database.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,33 @@ by adding a couple of class properties to your test.
protected $basePath = 'path/to/database/files';
}

**$migrate**

This boolean value determines whether the database migration runs before test.
By default, the database is always migrated to the latest available state as defined by ``$namespace``.
If false, migration never runs. If you want to disable migration, set false.

**$migrateOnce**

This boolean value determines whether the database migration runs only once. If you want
to run migration once before the first test, set true. If not present or false, migration
runs before each test.

**$refresh**

This boolean value determines whether the database is completely refreshed before every test. If true,
all migrations are rolled back to version 0. The database is always migrated to the latest available
state as defined by ``$namespace``.
This boolean value determines whether the database is completely refreshed before test. If true,
all migrations are rolled back to version 0.

**$seed**

If present and not empty, this specifies the name of a Seed file that is used to populate the database with
test data prior to every test running.
test data prior to test running.

**$seedOnce**

This boolean value determines whether the database seeding runs only once. If you want
to run database seeding once before the first test, set true. If not present or false, database seeding
runs before each test.

**$basePath**

Expand Down

0 comments on commit 51d4611

Please sign in to comment.