December 22, 2018 by Glenn

Run Phinx Database Migrations With Codeception

One of my legacy applications uses a mix of Phinx to handle my database migrations and Codeception to handle my acceptance testing suite. However I primarily develop in Laravel and have gotten a bit spoiled by their easy testing setup. When I run my test suite in Laravel it refreshes my testing database with the latest migrations. I wanted to acheive the same thing with Codeception.

Codeception gives you the option out of the box to refresh your testing database when you run your test suite using a sql dump. This is convenient but I didn't want to have to create a new dump every time I updated my migrations, I'd rather it just work.

It took me awhile but after enough digging I found all the information necessary to do this between the docs on both sites, and it's actually fairly easy. So I figured I'd compile the info here for anyone interested.


Firstly, we want to add a new connection to our enviornments array in our phinx.yml file. I call the connection testing and supply it with the credentials for my testing database.

Phinx accepts either a phinx.yml file or a phinx.php file. I go the php route so that I can make use of Dotenv for environment variables. You can use whichever format works for you.

<?php

require 'vendor/autoload.php';

$dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv->load();

return [
    'paths' => [
        'migrations' => '%%PHINX_CONFIG_DIR%%/db/migrations',
        'seeds' => '%%PHINX_CONFIG_DIR%%/db/seeds',
    ],
    'environments' => [
        'default_database' => getenv('APP_ENV'),
        'default_migration_table' => 'phinxlog',
        'local' => [
            'adapter' => 'mysql',
            'host' => getenv('DB_HOST'),
            'name' => getenv('DB_DATABASE'),
            'user' => getenv('DB_USERNAME'),
            'pass' => getenv('DB_PASSWORD'),
            'port' => 3306,
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
        ],
        'testing' => [
            'adapter' => 'mysql',
            'host' => getenv('DB_TESTING_HOST'),
            'name' => getenv('DB_TESTING_DATABASE'),
            'user' => getenv('DB_TESTING_USERNAME'),
            'pass' => getenv('DB_TESTING_PASSWORD'),
            'port' => 3306,
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
        ]
    ],
];

In the enviornments array you would probably want to add in another array for production as well. But for the sake of this post all we really need is our testing connection.

Next you'll want to open up and modify your tests/_support/Helper/Acceptance.php file.

<?php

namespace Helper;

use Phinx\Console\PhinxApplication;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\NullOutput;

class Acceptance extends \Codeception\Module
{
    public function _before($settings = [])
    {
        $app = new PhinxApplication();
        $app->setAutoExit(false);
        $app->run(new StringInput('rollback -e testing -t 0'), new NullOutput());
        $app->run(new StringInput('migrate -e testing'), new NullOutput());
        $app->run(new StringInput('seed -e testing'), new NullOutput());
    }
}

The -e testing is the important thing to note here, as it instructs Phinx to use our testing environment we setup. Also noteworthy is the -t 0 flag at the end of the rollback command, this tells Phinx to rollback all of your database migrations and start from scratch.


That's pretty much it. Simple right?

Join my mailing list

Subscribe now to stay up to date on whatever cool stuff I'm working on.