From 4fd852809bc60fd716a1620b6ad6f252e8f8f6b1 Mon Sep 17 00:00:00 2001 From: jpramirez Date: Mon, 20 Sep 2021 00:25:57 +0200 Subject: [PATCH] Allow run migrations without truncating (#24) (#25) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Allow run migrations without truncating (#24) * Allow run migrations without truncating * Truncate all connections by default * Update Documentation * Require migration plugin version ^3.1 Co-authored-by: Raúl Arellano --- README.md | 45 +++++++++++++++++++++++++-------- composer.json | 2 +- src/Migrator.php | 42 +++++++++++++++++++++++++----- tests/TestCase/MigratorTest.php | 17 +++++++++++++ 4 files changed, 88 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 102261d..c32cac1 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ With the CakePHP Test Migrator, the schema of both default and test DB are handl The package proposes a tool to run your [migrations](https://book.cakephp.org/migrations/3/en/index.html) once prior to the tests. In order to do so, you may place the following in your `tests/bootstrap.php`: -```$xslt +```php \CakephpTestMigrator\Migrator::migrate(); ``` This command will ensure that your migrations are well run and keeps the test DB(s) up to date. Since tables are truncated but never dropped by the present package's fixture manager, migrations will be run strictly when needed, namely only after a new migration was created by the developer. @@ -30,23 +30,38 @@ The `Migrator`approach presents the following advantages: * it eases the maintenance of your tests, since regular and test DBs are managed the same way, * it indirectly tests your migrations. -You may pass `true` as the second argument for a verbose output on the console. +You may pass `true` as the second argument for a verbose output on the console. + +### Options + +| name | type | default | description | +| ---- | ---- | ------- | ----------- | +| verbose | *bool* | `false` | Print info about migrations done | +| truncate | *bool* | `true` | Truncate all tables after migrations are done. You can call `truncate()` manually | + +You can pass a boolean as options, it will be used as `verbose` + +```php +\CakephpTestMigrator\Migrator::migrate([], true); +// is the same as +\CakephpTestMigrator\Migrator::migrate([], ['verbose' => true]); +``` ### Multiple migrations settings You can pass the various migrations directly in the Migrator instantiation: -```$xslt +```php \CakephpTestMigrator\Migrator::migrate([ ['connection' => 'test', 'source' => 'TestFolder'], ['plugin' => 'FooPlugin', 'connection' => 'FooConnection'], ['source' => 'BarFolder'], ... - ], true); + ], ['verbose' => true]); ``` You can also pass the various migrations directly in your Datasource configuration, under the key `migrations`: -```$xslt -In config/app.php +```php +// In config/app.php 'test' => [ 'className' => Connection::class, 'driver' => Mysql::class, @@ -68,7 +83,7 @@ You can set `migrations` simply to `true` if you which to use the default migrat ### Migrations status Information on a connection's migration status will be obtained as follows: -``` +```php $migrator = Migrator::migrate(); $connectionsWithModifiedStatus = $migrator->getConnectionsWithModifiedStatus(); ``` @@ -76,6 +91,16 @@ $connectionsWithModifiedStatus = $migrator->getConnectionsWithModifiedStatus(); the method `getConnectionsWithModifiedStatus` returning a list of the connections with down migrations prior to running the migrations. +### Data truncation + +Use **truncate** option to truncate (or not) after migrations are done. This is useful if you need to do other tasks in the test suite bootstrap + +```php +$migrator = Migrator::migrate([], ['truncate' => false]); +// do something with the migrated database (bake fixtures, etc) +$migrator->truncate(); +``` + ### What happens if I switch branches? If you ever switched to a branch with nonexistent up migrations, you've moved to a branch in a past state. @@ -86,18 +111,18 @@ does not require any intervention on your side. The `Migrator::dump()` will help you import any schema from one or several sql file. Run for example: -```$xslt +```php Migrator::dump('test', 'path/to/file.sql') ``` or with multiples files -```$xslt +```php Migrator::dump('test', [ 'path1/to/file1.sql', 'path2/to/file2.sql', ]) ``` or for a verbose output -```$xslt +```php Migrator::dump('test', 'path/to/file.sql', true) ``` diff --git a/composer.json b/composer.json index 3bc7eeb..f9388d4 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ }, "require-dev": { "cakephp/cakephp-codesniffer": "^4.0", - "cakephp/migrations": "^3.0", + "cakephp/migrations": "^3.1", "josegonzalez/dotenv": "dev-master", "phpunit/phpunit": "^8.0" }, diff --git a/src/Migrator.php b/src/Migrator.php index 1035067..7f1bd8a 100644 --- a/src/Migrator.php +++ b/src/Migrator.php @@ -55,18 +55,33 @@ final public function __construct(bool $verbose, ?ConfigReader $configReader = n * General command to run before your tests run * E.g. in tests/bootstrap.php * + * Options: + * - verbose | bool | Set to true to display messages + * - truncate | bool | Truncate tables after migrations are done. + * * @param array $config - * @param bool $verbose Set to true to display messages + * @param array{verbose?:bool,truncate?:bool}|bool $options Options for migrations * @return Migrator */ - public static function migrate(array $config = [], $verbose = false): Migrator + public static function migrate(array $config = [], $options = []): Migrator { - $migrator = new static($verbose); + if ($options === true || $options === false) { + $options = ['verbose' => $options]; + } + $options += [ + 'verbose' => false, + 'truncate' => true, + ]; + $migrator = new static($options['verbose']); $migrator->configReader->readMigrationsInDatasources(); $migrator->configReader->readConfig($config); $migrator->handleMigrationsStatus(); + if ($options['truncate']) { + $migrator->truncate(); + } + return $migrator; } @@ -129,6 +144,23 @@ protected function runMigrations(array $config): void } } + /** + * Truncates connections on demand. + * + * @param string[]|null $connections Connections names to truncate. Defaults to modified connections + * @return void + */ + public function truncate(?array $connections = null): void + { + if ($connections === null) { + $connections = $this->configReader->getActiveConnections(); + } + $schemaCleaner = new SchemaCleaner($this->io); + foreach ($connections as $connectionName) { + $schemaCleaner->truncate($connectionName); + } + } + /** * If a migration is missing or down, all tables of the considered connection are dropped. * @@ -163,10 +195,6 @@ protected function handleMigrationsStatus(): self $this->runMigrations($config); } - foreach ($this->connectionsWithModifiedStatus as $connectionName) { - $schemaCleaner->truncate($connectionName); - } - return $this; } diff --git a/tests/TestCase/MigratorTest.php b/tests/TestCase/MigratorTest.php index cfcfb47..83d0e48 100644 --- a/tests/TestCase/MigratorTest.php +++ b/tests/TestCase/MigratorTest.php @@ -107,4 +107,21 @@ public function testDropTablesForMissingMigrations(): void $count = $connection->newQuery()->select('version')->from('phinxlog')->execute()->count(); $this->assertSame(3, $count); } + + public function testMigrateWithoutTruncate(): void + { + $connection = ConnectionManager::get('test'); + $cleaner = new SchemaCleaner(); + $cleaner->drop('test'); + + $migrator = Migrator::migrate([], ['truncate' => false]); + + $count = $connection->newQuery()->select('title')->from('articles')->execute()->count(); + $this->assertSame(1, $count); + + $migrator->truncate(); + + $count = $connection->newQuery()->select('title')->from('articles')->execute()->count(); + $this->assertSame(0, $count); + } }