Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

johnny's avatar

Codeception doesn't roll back the database

Hi guys,

I have a login test, which works fine on the first run

vendor/bin/codecept run functional
Codeception PHP Testing Framework v2.0.2
Powered by PHPUnit 4.3.5 by Sebastian Bergmann.

Functional Tests (1) -----------------------------------------------------------------------------------------------
Trying to log in to my account (LoginCept)                                                                     Ok
--------------------------------------------------------------------------------------------------------------------


Time: 4.51 seconds, Memory: 23.00Mb

OK (1 test, 3 assertions)

but if I ran it again, it fails, because the database contains the data from the previous test and my user's account id won't match.

Functional Tests (1) -----------------------------------------------------------------------------------------------
Trying to log in to my account (LoginCept)                                                                     Fail
--------------------------------------------------------------------------------------------------------------------


Time: 4.72 seconds, Memory: 23.25Mb

There was 1 failure:

---------
1) Failed to log in to my account in LoginCept (/home/vagrant/Sites/Clients/Pazo/CRM/app/tests/functional/LoginCept.php)
Couldn't see current url equals "/1/dashboard":
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'/1/dashboard'
+'/2/dashboard'

Scenario Steps:
6. I see current url equals "/1/dashboard"
5. I click "Login"
4. I fill field "password","secret"
3. I fill field "email","test@example.com"
2. I am on page "/login"
1. I have a user {"user":{"email":"test@example.com","password":"secret"},"user_meta":{"first_name":"Test","last_name":"User"},"account":{"plan":"trial"},"account_meta":{"name":"My Awesome Company"}}


FAILURES!                            
Tests: 1, Assertions: 1, Failures: 1.

Any idea how to fix this?

0 likes
11 replies
anchour's avatar

Where's the code that's running the migration before the test is run? Couldn't you just do a dump of your test database and set Codeception to revert to that after all the tests have been executed?

johnny's avatar

I don't use the dump file, but the on the Laravel4 module's documentation you can read this in the configuration section:

cleanup: boolean, default true - all db queries will be run in transaction, which will be rolled back at the end of test.

So, in theory it should roll back all the query at the end of the test. Or am I missing something?

MikeHopley's avatar

Can you post your acceptance.suite.yml file?

I am not sure the Laravel4 module can be used when running acceptance tests. Acceptance tests are technically very different from "normal" tests, because they run in a browser (a "real" browser or a headless one).

I don't think the Webdriver or PHPbrowser modules are compatible with the Laravel4 module.

The documentation recommends using a DB dump for acceptance test cleanup. I do know this works!

NathanIsaac's avatar

Hello,

I am having the same issue. Here is my functional.suite.yml file:


class_name: FunctionalTester modules: enabled: [Filesystem, FunctionalHelper, Laravel4, Asserts] config: Laravel4: environment: 'testing' cleanup: true filters: true

I am running some queries with DB::insert() and with TestDummy::create(). Does that not work with cleanup: true?

This is strange because this seems to work in one of my other project. I'm trying to figure out why it's not working in this project.

Thanks,

Nathan

NathanIsaac's avatar

@johnny I sure did. The fix is to use DB Transactions.

<?php
use \FunctionalTester;
use Laracasts\TestDummy\Factory as TestDummy;

class EventsApiCest
{
    public function _before(FunctionalTester $I)
    {
        DB::connection('non-default-connection')->beginTransaction();
    }

    public function _after(FunctionalTester $I)
    {
        DB::connection('non-default-connection')->rollBack();
    }

    public function view_all_events(FunctionalTester $I)
    {
        TestDummy::create('Models\Event', [
            'location' => 'Supper Awesome Location',
            'description' => 'The best event ever!',
        ]);

        $I->sendGET('api/v2/events');

        $I->seeResponseCodeIs(200);
        $I->seeResponseContainsJson([
            'location' => 'Supper Awesome Location',
            'description' => 'The best event ever!',
        ]);
    }
}

The reason this wasn't working for me was because I was using the non default db connection found in the app\config\database.php file.

<?php

return array(

        //...
    /*
    |--------------------------------------------------------------------------
    | Default Database Connection Name
    |--------------------------------------------------------------------------
    |
    | Here you may specify which of the database connections below you wish
    | to use as your default connection for all database work. Of course
    | you may use many connections at once using the Database library.
    |
    */

    'default' => 'sqlsrv',

        'connections' => array(

        'sqlsrv' => array(
            'driver'   => 'sqlsrv',
            'host'     => 'localhost',
            'database' => 'db',
            'username' => '',
            'password' => '',
            'prefix'   => '',
        ),

         'non-default-connection' => array(
            'driver'   => 'sqlsrv',
            'host'     => 'localhost',
            'database' => 'db2',
            'username' => '',
            'password' => '',
            'prefix'   => '',
        ),

    ),
        //...
);

Does that help?

1 like
seb7's avatar

Hi,

I also had trouble with cleanup & fixture.

What you can do is to use a sqlite :memory: database and run artisan::call('migrate') before each tests. This way everything is fine :) Then on each test, I use testdummy to create the object I need for my tests. No need to maintain a dump, no way to add data in database that may break other tests.

This may not be good for large project with many tables, but for a small app, that's good.

johnny's avatar

@nisaac2fly, @seb7 I created a dump.sql file (which I keep up-to-date with the latest migrations) and use the Db module of Codeception and it does everything automatically.

...
modules:
    config:
        Db:
            dsn: 'mysql:host=localhost;dbname=dbname'
            user: 'homestead'
            password: 'secret'
            dump: app/tests/dump.sql
...
seb7's avatar

yep, this works fine, I know. I prefere using an empty db and populate it just in the test with testdummy, more easy to maintain. Just my way...

NathanIsaac's avatar

@johnny, @seb7 yeah that does make sense. The reason I use transactions is because I work for a larger company which in turn makes more sense to use DB Transactions.

1 like

Please or to participate in this conversation.