Search code examples
laraveltestingautomated-testsdatabase-connectionbehat

Laravel Behat DB connection


I've been having issues with behat and laravel working together. I configured Behat with Laravel. I have this simple scenario:

Scenario: Login as an admin Given I add an admin to the db When I login as an admin Then I should be in the welcome page

In the FeatureContext Class I insert the admin user to the db using factories.

Everything works fine if I don't use the browser. But, when I start the selenium server and I add the @javascript tag to the Scenario, the test run fine, the browser start fine, but the login process fails because there is no users in the db. Yes the same user with the same credentials that I just added in the first step. Also I checked for the user by querying the db before executing the login, and the user is there.

BTW, I only have one connection, I triple-checked that.

So, what is happening here? Any Ideas?

Thanks.


Solution

  • I think I solved the issue or at least I found a workaround.

    For some reason DB::beginTransaction() and DB::rollback() does not work properly when the browser is launched with behat and selenium. After some time of researching I came up with the next solution. Apparently, because I am using a vagrant virtual machine to launch my application, when the browser is launched by Selenium, it start a new session. Also, it uses another instance of laravel, not the same instance behat is working with. That means that the transactions I am trying to implement with behat never affect the same database the application is using with the browser. Additionally, I am using a different .env configuration file for my tests (.env.testing) where I defined all the parameters that laravel need to use for the test environment but there is no way to tell the application through the browser that it was launched by behat and selenium and to change to the test environment, instead, thw application will be using the regular environment configuration file, in my case .env (development).

    Please see bellow the code I came up with:

    ```

     /**
     * @javascript
     * @BeforeFeature
     */
    public static function before(BeforeFeatureScope $scope)
    {
        putenv('APP_ENV=local');
    
        $tableNames = Schema::getConnection()->getDoctrineSchemaManager()->listTableNames();
    
        DB::statement('SET FOREIGN_KEY_CHECKS = 0');
    
        foreach ($tableNames as $name) {
            //if you don't want to truncate migrations
            if ($name == 'migrations') {
                continue;
            }
            DB::table($name)->delete();
        }
        DB::statement('SET FOREIGN_KEY_CHECKS = 1');
    
        Artisan::call('migrate');
    
        try {
            Artisan::call('db:seed');
        } catch (Exception $e) {
            dump('seeder failed');
        }
    }
    
    
     /**
     * @javascript
     * @AfterFeature
     */
    public static function after(AfterFeatureScope $scope)
    {
        putenv('APP_ENV=local');
        Artisan::call('migrate:rollback');
    
        $tableNames = Schema::getConnection()->getDoctrineSchemaManager()->listTableNames();
        DB::statement('SET FOREIGN_KEY_CHECKS = 0');
    
        foreach ($tableNames as $name) {
            //if you don't want to truncate migrations
            if ($name == 'migrations') {
                continue;
            }
            DB::table($name)->delete();
            //Schema::dropIfExists($name);
        }
        DB::statement('SET FOREIGN_KEY_CHECKS = 1');
    }
    

    ```

    A solution to tell the application inside the vagrant machine which environment use could be a configuration in the web server inside the vagrant machine that based on a the url, loads the app with a different a environment. For example:

    standar url: https://localhost:8000/auth/login test url: https://localhost:8000/test/auth/login

    In this case all the application urls will have test in it.

    Hopefully this would help to somebody in the future. If anybody have a better approach, please, I will be more than welcome try it.

    Cheers