Skip to content

Commit

Permalink
Allow run migrations without truncating (#24) (#25)
Browse files Browse the repository at this point in the history
* 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 <raul338@elhacker.net>
  • Loading branch information
pabloelcolombiano and raul338 authored Sep 19, 2021
1 parent 280abc2 commit 4fd8528
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 18 deletions.
45 changes: 35 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
Expand All @@ -68,14 +83,24 @@ 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();
```

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.
Expand All @@ -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)
```

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
42 changes: 35 additions & 7 deletions src/Migrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -163,10 +195,6 @@ protected function handleMigrationsStatus(): self
$this->runMigrations($config);
}

foreach ($this->connectionsWithModifiedStatus as $connectionName) {
$schemaCleaner->truncate($connectionName);
}

return $this;
}

Expand Down
17 changes: 17 additions & 0 deletions tests/TestCase/MigratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

0 comments on commit 4fd8528

Please sign in to comment.