A tool to run migrations prior to running tests

Overview

cakephp-test-migrator

A tool to run migrations prior to running tests

The Migrator

For CakePHP 3.x

composer require --dev vierge-noire/cakephp-test-migrator "^1.0"

For CakePHP 4.x

composer require --dev vierge-noire/cakephp-test-migrator "^2.0"

Introduction

CakePHP fixtures handle the test DB schema in a paralell manner to the default DB. On the one hand you will write migrations for your default DB. On the other hand you either hard coded describe the schema structure in your fixtures, or meme the default DB. The later is simpler, but it forces you to have two DBs. And in CI tools, you will have to run the migrations on your default DB, and the fixtures meme the default DB. So why not running migrations directly on the test DB?

With the CakePHP Test Migrator, the schema of both default and test DB are handled exactly in the same way. You do not necessarily need a default DB. Tables are not dropped between test suites, which speeds up your tests. And migrations are part of the whole testing process: they get indirectly tested.

Setting

The package proposes a tool to run your migrations once prior to the tests. In order to do so, you may place the following in your tests/bootstrap.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.

The Migratorapproach presents the following advantages:

  • it improves the speed of the test suites by avoiding the creation and dropping of tables between each test case classes,
  • 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.

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

\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:

\CakephpTestMigrator\Migrator::migrate([
    ['connection' => 'test', 'source' => 'TestFolder'],       
    ['plugin' => 'FooPlugin', 'connection' => 'FooConnection'],      
    ['source' => 'BarFolder'],
    ...
 ], ['verbose' => true]);

You can also pass the various migrations directly in your Datasource configuration, under the key migrations:

// In config/app.php
'test' => [
    'className' => Connection::class,
    'driver' => Mysql::class,
    'persistent' => false,
    'timezone' => 'UTC',
    'flags' => [],
    'cacheMetadata' => true,
    'quoteIdentifiers' => false,
    'log' => false,
    'migrations' => [
        ['plugin' => 'FooPlugin'],      
        ['source' => 'BarFolder'],
    ],
],

You can set migrations simply to true if you which to use the default migration settings.

Migrations status

Information on a connection's migration status will be obtained as follows:

$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

$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. The Migrator will automatically drop the tables where needed, and re-run the migrations. Switching branches therefore does not require any intervention on your side.

What if I do not use migrations?

The Migrator::dump() will help you import any schema from one or several sql file. Run for example:

Migrator::dump('test', 'path/to/file.sql')

or with multiples files

Migrator::dump('test', [
    'path1/to/file1.sql',
    'path2/to/file2.sql',
])

or for a verbose output

Migrator::dump('test', 'path/to/file.sql', true)

The first argument is the name of the connection, the second the file(s) to dump, the third the verbosity (boolean).

This method will however drop the schema prior to recreating it, which presents a significant loss of performance in comparison to the migration-based solution.

Trouble shooting

It might be required, right after you installed or updated the plugin, to drop and recreate your test database. If the problem persists, feel free to open an issue.

Authors

  • Juan Pablo Ramirez
  • Nicolas Masson

Support

Contact us at [email protected] for professional assistance.

You like our work? ko-fi

License

The CakephpTestMigrator plugin is offered under an MIT license.

Copyright 2020 Juan Pablo Ramirez and Nicolas Masson

Licensed under The MIT License Redistributions of files must retain the above copyright notice.

Comments
  • Allow to truncating tables later

    Allow to truncating tables later

    Related to #20

    I have a project where in some tables i have inserted some constants, like this

    $table->addColumn('name', 'string');
    // $table->addColumn(...);
    $table->create();
    $table->insert([
        [
            'id' => \App\Model\Entity\ArticleStates::ARTICLE_NEW,
            'name' => 'New',
            // ...
        ],
        // ....
    ]);
    $table->save();
    

    When using the migrator, if migrations changed, I bake fixtures but this results empty because the migrator truncates it.

    // tests/bootstrap.php
    $migrator = \CakephpTestMigrator\Migrator::migrate();
    $modified = $migrator->getConnectionsWithModifiedStatus();
    if (count($modified)) {
       // re-bake fixtures... 
       // here i would need the db not truncated
       // and call "truncate()" manually
    }
    

    A solution could be passing an options array for second parameter of Migrator::migrate()

    opened by raul338 8
  • Adding it to the migrations plugin

    Adding it to the migrations plugin

    Do you have plans to make this part of the migrations plugin directly? This would probably help especially plugins a lot to verify their migrations.

    They already have a require-dev usually on Migrations So having an easy to use test harness then would be super useful I would imagine.

    opened by dereuromark 7
  • Allow check for migrations

    Allow check for migrations

    Hi!

    I would like to check if there is a migration pending, but instead of runing migrations, i would launch another command.

    In my case this command runs migrations, run some other commands and bake some fixtures (e.g ACL acos table)

    I think that adding a wrapper for isStatusChanged would suffice. So I can do something like this:

    $migrator = CakephpTestMigrator\Migrator(true);
    $migrator->configReader->readMigrationsInDatasources();
    $migrator->configReader->readConfig([
       ['plugin' => 'Acl'],
       []
    ]);
    if ($migrator->isStatusChanged()) {
       // launch commands, run migrations, re-bake fixtures, etc
    }
    

    If you agree i can try open a PR

    Thanks for the plugin!

    opened by raul338 5
  • cake3 Migrator::migrate with plugin throws PluginNotFoundException

    cake3 Migrator::migrate with plugin throws PluginNotFoundException

    Today I wanted to load the Tags Plugin into a cakephp 3.10 project with fixture_factories 1.5. As with another project of mine with cake4, I wanted to load the Tags Plugin fixtures with Migrator::migrate( [['connection' => 'test'], ['plugin' => 'Tags']], ['verbose' => true]);, but it gave me the error that the Plugin can't be loaded. It seems like the PluginCollection.php class in cake4 will create a plugin if it isn't loaded, as can be seen in: https://github.com/cakephp/core/blob/bed4b6f09550909beea5440627d5a6ff85fb1934/PluginCollection.php#L213. In Cake3 it just throws an error and I have no idea how to load a plugin in tests/bootstrap.php as there is no Plugin::load() anymore. It might not be a issue of fixture_factories, but I haven't found anything in the docs that point out how to load a plugin. It must work somehow, beacause otherwise I couldn't explain why there even is a config parameter plugin in Migrator::migrate. Do you have an example how to load a plugin fixture with cake3 and fixture_factories? Thank you!

    opened by gringlas 3
  • Support dump files

    Support dump files

    Hello!

    I am trying to use this plugin in an existing CakePHP 4 project. However, after changing the PHPUnit configuration file, my tests no longer run. The error it presents is:

    Base table or view not found: 1146 Table 'database.table' doesn't exist.

    In all my current fixtures, I import the table definition of the default connection, using public $import = ['table' => 'table_name'];

    How can I use the plugin but keep the current tests working?

    In the CI / CD pipeline we execute a .sql file with all CREATE TABLE in the default connection. We do not use the Migrations plugin, as we have a legacy system since the time of Cake 1. Migrations at that time did not meet our requirements. In the pipeline it will be easy to execute this SQL file in the test connection, but I think what it would be like in a development environment when running a single test class. Currently, the complete database contains almost 300 tables. Performing the creation of all of these tables before a single test would be costly.

    enhancement 
    opened by gersonfs 2
  • Migrator is always truncating table though no migrations have been done

    Migrator is always truncating table though no migrations have been done

    Hello @pabloelcolombiano

    I'm there again ^^ Hope you're going well.

    I was upgrading an app from 4.2x to 4.3x. and so vierge-noire packages. After upgrading, a really simple TestCase that implies no database interaction was badly delayed at start (I was previously using skipTablesTruncation trait).

    By now, I'm on 4.3.8 for cakephp and 2.5 for migrator on this app.

    I've first applied the "fixture upgrade" but it didn't help.

    The culprit is the migrator that was running truncations on all tables though no migration have been deployed. I've disabled truncation as explained and now it rocks again.

    BUT I'm wondering why this test was launching so quickly in the previous setup and not in the new ? By the way, why choosing to truncate tables as default after a migration in the test environment that should be "hand-cleaned" if needed before the TestCase/test ?

    Unfortunately, I don't have any time by now to figure it out so I'm opening this issue . If it seems non relevant to you, feel free to close it 😄

    opened by liqueurdetoile 1
  • Allow run migrations without truncating

    Allow run migrations without truncating

    Closes #23

    Implementation based on comment on that issue

    In the test its required to clean the connection first, as other test before can leave it migrated.

    opened by raul338 1
  • Make the migrator independent from the test suite light

    Make the migrator independent from the test suite light

    The dropping of the schema should be independent of the test suite light.

    Schema droppers should be implemented for all SQL engines.

    The tests dedicated .env files will be moved in the tests folder.

    enhancement 
    opened by pabloelcolombiano 1
Releases(v2.5)
Owner
Vierge Noire
Vierge Noire
To run time/IO related unit tests (e.g., sleep function calls, database queries, API calls, etc) faster using Swoole.

To run time/IO related unit tests (e.g., sleep function calls, database queries, API calls, etc) faster using Swoole.

Demin Yin 11 Sep 9, 2022
PHP Test Generator - A CLI tool which generates unit tests

This project make usages of PHPStan and PHPParser to generate test cases for a given PHP File.

Alexander Schranz 7 Dec 3, 2022
Mock HTTP requests on the server side in your PHP unit tests

HTTP Mock for PHP Mock HTTP requests on the server side in your PHP unit tests. HTTP Mock for PHP mocks the server side of an HTTP request to allow in

InterNations GmbH 386 Dec 27, 2022
vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with any unit test framework, like PHPUnit or SimpleTest.

vfsStream vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with

null 1.4k Dec 23, 2022
Some shorthand functions for skipping and focusing tests.

Pest Plugin: Shorthands This repository contains the Pest Plugin Shorthands. If you want to start testing your application with Pest, visit the main P

Thomas Le Duc 10 Jun 24, 2022
A PHP library for mocking date and time in tests

ClockMock Slope s.r.l. ClockMock provides a way for mocking the current timestamp used by PHP for \DateTime(Immutable) objects and date/time related f

Slope 44 Dec 7, 2022
Magic Test allows you to write browser tests by simply clicking around on the application being tested, all without the slowness of constantly restarting the testing environment.

Magic Test for Laravel Magic Test allows you to write browser tests by simply clicking around on the application being tested, all without the slownes

null 400 Jan 5, 2023
Wraps your Pest suite in a Laravel application instance, allowing global use of the framework in tests.

Pest Larastrap Plugin This is currently a highly experimental project and is subject to large pre-release changes. Pest PHP is an awesome PHP testing

Luke Downing 3 Jan 6, 2022
TestDummy makes the process of preparing factories (dummy data) for your integration tests as easy as possible

TestDummy TestDummy makes the process of preparing factories (dummy data) for your integration tests as easy as possible. As easy as... Build a Post m

Laracasts 461 Sep 28, 2022
Extension to use built-in PHP server on Behat tests

Extension to use built-in PHP server on Behat tests Instalation composer require libresign/behat-builtin-extension Configuration Add the extension to

LibreSign 2 Feb 21, 2022
Enforce consistent styling for your Pest PHP tests

A set of PHP CS rules for formatting Pest PHP tests.

Worksome 2 Mar 15, 2022
This plugin adds basic HTTP requests functionality to Pest tests, using minicli/curly

Curly Pest Plugin This plugin adds basic HTTP requests functionality to Pest tests, using minicli/curly. Installation composer require minicli/pest-pl

minicli 16 Mar 24, 2022
Example repo for writing tests in Drupal (using DDEV)

Drupal Test Writing This is a test D9 site which can be used for practicing test writing and running.

David Stinemetze 13 Nov 14, 2022
Report high memory usage PHPUnit tests: Managed by opg-org-infra & Terraform

phpunit-memory-usage Report high memory usage PHPUnit tests: Managed by opg-org-infra & Terraform Configuration Add into the phpunit.xml extensions se

Ministry of Justice 2 Aug 4, 2022
Prevent none-test output in your Pest tests.

Pest Plugin Silence Often, when writing tests, we echo and dump test code to debug and check everything is working correctly. It can be easy to forget

Worksome 5 Feb 23, 2022
Allows the running of PHPUnit within ExpressionEngine

EE Unit Tests EE Unit Tests is an Add-on for ExpressionEngine that allows developers to execute unit tests from the Command Line. EE Unit Tests uses P

Eric Lamb 6 Jan 14, 2022
Very simple mock HTTP Server for testing Restful API, running via Docker.

httpdock Very simple mock HTTP Server for testing Restful API, running via Docker. Start Server Starting this server via command: docker run -ti -d -p

Vo Duy Tuan 4 Dec 24, 2021
A Composer script to run a 'test' or 'spec' Composer script against multiple PHP versions.

composer-multitest composer-multitest is a Composer script that runs a test or spec Composer script against multiple PHP versions managed by PHPBrew o

Raphael Stolt 5 Aug 27, 2019
This component provides functions unavailable in releases prior to PHP 8.0.

This component provides functions unavailable in releases prior to PHP 8.0.

Symfony 1.5k Dec 29, 2022
Database migrations for PHP ala ActiveRecord Migrations with support for MySQL, Postgres, SQLite

Introduction Ruckusing is a framework written in PHP5 for generating and managing a set of "database migrations". Database migrations are declarative

Cody Caughlan 506 Nov 17, 2022