How to migrate a testing database in Laravel 5?

Published 2 years ago by mabasic

I have setup Codeception and Laravel 5 to work. And they work.

But now, I want to run codeception with a testing database, not local.

So in functional.suite.yml I have:

class_name: FunctionalTester
modules:
    enabled: [Filesystem, FunctionalHelper, Laravel5]
    config:
      Laravel5:
        environment_file: .env.testing

And that works. It loads the values from .env.testing and runs test on testing database.

The problem now is that I want to migrate the testing database before running the tests.

I do php artisan migrate --env=testing but that migrates my local database specified in .env file.

Is there a way to migrate a database different from one specified in .env ?

Best Answer (As Selected By mabasic)
mabasic

I have found a workaround for this.

In your config/database.php bellow mysql add:

        'mysql_testing' => [
            'driver'    => 'mysql',
            'host'      => env('TESTING_DB_HOST', 'localhost'),
            'database'  => env('TESTING_DB_DATABASE', 'forge'),
            'username'  => env('TESTING_DB_USERNAME', 'forge'),
            'password'  => env('TESTING_DB_PASSWORD', ''),
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
            'strict'    => false,
        ],

And now in your .env add the values for:

TESTING_DB_HOST=localhost
TESTING_DB_DATABASE=homestead_testing
TESTING_DB_USERNAME=homestead
TESTING_DB_PASSWORD=secret

Now you can run

php artisan migrate --database=mysql_testing

And it will migrate your testing database.

mabasic

I have found a workaround for this.

In your config/database.php bellow mysql add:

        'mysql_testing' => [
            'driver'    => 'mysql',
            'host'      => env('TESTING_DB_HOST', 'localhost'),
            'database'  => env('TESTING_DB_DATABASE', 'forge'),
            'username'  => env('TESTING_DB_USERNAME', 'forge'),
            'password'  => env('TESTING_DB_PASSWORD', ''),
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
            'strict'    => false,
        ],

And now in your .env add the values for:

TESTING_DB_HOST=localhost
TESTING_DB_DATABASE=homestead_testing
TESTING_DB_USERNAME=homestead
TESTING_DB_PASSWORD=secret

Now you can run

php artisan migrate --database=mysql_testing

And it will migrate your testing database.

IsraelOrtuno

You could do it that way, however, mysql will keep the data for your future tests. As you might have done some changes in your database, I don't find this as the perfect approach.

What I do is to edit codeception.yml file to set:

modules:
    config:
        Db:
            dsn: 'mysql:host=localhost;dbname=myapp_testing'
            user: 'homestead'
            password: 'secret'
            dump: tests/_data/dump.sql
            cleanup: true

Note the cleanup set to "true". This will truncate the database every time you run your tests.

I have previously exported my database into dump.slq using

mysqldump myapp_testing -uhomestead > tests/_data/dump.sql

This way you are always testing from the same database data and structure.

mabasic

I have considered your approach, but when using Laravel5 module for Codeception every functional test is run in transaction mode. So at the end of the test I still have clean database for the next test

Your approach does not fit me, because I am at a stage where I use migrations a lot. And if I add a new migration I would have to do a new mysql dump for each migration which becomes a waste of time.

novica.vukobratovic

Thanks a lot @mabasic I've been going crazy over this for like an hour already, trying to figure it out.

Krasho

Hi @mabasic, I Use your configuration, but, If I have an autoincrement field, that does not start in one for the next test. How can I do that? Could I truncate the table?

Kind reguards.

24nettbutikk

@Krasho Run your database interactions inside a transaction so that any changes are rolled back at the end of the test. A better choice, if you want to test your database, is to use an sqlite database, which is much faster. To reset the database, all you need to do is copy in the physical file that is your database before the tests run.

antennaio

This is a very informative thread. What I'm currently doing is I automate the step of creating a fresh database dump whenever Codeception is run.

https://github.com/antennaio/laravel-codeception-dbdump

Please sign in or create an account to participate in this conversation.