Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Migrate only once with Laravel dusk

According to the "Database Testing" documentation I can reset the database after each test (first option). Second option is to run test using Transactions. It seems a better approach to me, but if I want to run with transaction, the migration does not run.

Is there any way to run the migration once for all the test process?

In other words, I want to run the migration, run every tests with transaction, then rollback. I tried with what the documentation says, but I think something is missing.

like image 285
rap-2-h Avatar asked Feb 01 '17 12:02

rap-2-h


3 Answers

Wrangled with this for a while today and running migrations in conjunction with migrations seems to do the trick. A snapshot of my test is as follows:

<?php

namespace Tests\Browser;

use App\User;
use Tests\DuskTestCase;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class DefaultTest extends DuskTestCase
{
    use DatabaseMigrations, DatabaseTransactions;

    /**
     * A Dusk test example.
     *
     * @return void
     */
    public function test_something()
    {
        //Add test stuff here
    }
}

I've got a couple of factories in my actual test and they seem to run through the migrations with the data destroyed after the test as expected.

like image 184
simnom Avatar answered Oct 23 '22 04:10

simnom


It is not possible to run DatabaseTransactions in combination with dusk for the moment.

https://github.com/laravel/dusk/issues/110

The creation of the user record and the use of it in the browser are done in two different processes. This means the created user is part of a database transaction which is not committed and thus not accessible by the browser process.

Database migrations work. So you should use those. Also make sure you run a seperate testing database so you don't mess with your production/development database.

https://laravel.com/docs/5.4/dusk#environment-handling

To force Dusk to use its own environment file when running tests, create a .env.dusk.{environment} file in the root of your project. For example, if you will be initiating the dusk command from your local environment, you should create a .env.dusk.local file.

When running tests, Dusk will back-up your .env file and rename your Dusk environment to .env. Once the tests have completed, your .env file will be restored.

The provided answer works because DatabaseMigrations work. The use DatabaseTransactions is not relevant.

like image 26
Christophvh Avatar answered Oct 23 '22 04:10

Christophvh


From what I understand, I don't think transactions can ever work when using dusk, as each browser request in dusk creates a separate instance of your laravel app.

Previously, phpunit would create a new application in memory as part of the process (in the setUp / createApplication method), then test against that testing application, then destroy it and set up the next one. As such, the transactions can be wrapped around (or just inside) the create and destroy parts of that application before it starts up a new database connection for the next test.

With dusk, it's real end-to-end testing (including a browser, faked user interaction, the routing on your local machine, etc.), which means it is not all contained within the environment that your tests are running in, like they usually are in phpunit.

Dusk does the following:

  • Copies your .env.dusk.* and launches the chromedriver (or whatever selenium-like thing you use)
  • Triggers a phpunit shell command (ie. new command, new process)
  • The phpunit command runs your dusk tests, which each open a browser window and makes requests (each request starting a new php-fpm and php process (for nginx)) - just as though you were making those requests yourself. Each of them have separate connections to the db, and so cannot interact with each others' transactions.

It's also worth noting that the DatabaseTransactions trait is in the Foundation package, not the Dusk package, so it's not build / packaged with Dusk in mind.

This also explains why in-memory sqlite doesn't work with dusk, as one process does not have access to another process' memory.

like image 37
Vinayak Kulkarni Avatar answered Oct 23 '22 04:10

Vinayak Kulkarni