tzookb's avatar

laravel sqlite database with codeception acceptance

I am creating great unit tests that work with an sqlite database, that on each test the sqlite database (in memory) gets a migrations and seeds.

the code:

class TestCase extends Illuminate\Foundation\Testing\TestCase {

protected $withDb = false;
 /**
  * Creates the application.
  *
  * @return \Symfony\Component\HttpKernel\HttpKernelInterface
  */
 public function createApplication()
 {
  $unitTesting = true;

  $testEnvironment = 'testing';

  return require __DIR__.'/../../bootstrap/start.php';
  }

  public function setUp()
  {
      parent::setUp(); // Don't forget this!

      $this->prepareForTests();
   }

   private function prepareForTests()
   {
       if ($this->withDb) {
          Artisan::call('migrate');

          Artisan::call('db:seed', ['--class' => 'TestingDatabaseSeeder']);
     }

    Mail::pretend(true);
 }
}

now I would like to use the in memory sqlite and use the migration for my accetance testing with codeception, any ideas how?

0 likes
1 reply
afrayedknot's avatar

I spent some time on this recently - and my conclusion is that you cannot use memory sqlite for acceptance tests - due to the way acceptance tests work. i.e. because you are making an 'external' request to the server from your client (i.e. you make a curl request to the server) - then you cant have a memory database.

I tried a few things - and it just kept causing weird errors and failing tests when it should otherwise work.

What I do instead, for all my tests, is create a 'stubdb.sqlite' file - and then literally make a copy of that file inbetween each test. It is ridicously fast - especially if you have an SSD drive.

So my config\database.php file looks like this:

  'mysqldev' => [
   'driver' => 'mysql',
   'host' => 'localhost',
   'database' => 'mpt',
   'username' => 'homestead',
   'password' => 'secret',
   'charset' => 'utf8',
   'collation' => 'utf8_unicode_ci',
   'prefix' => '',
  ],

        'testingsetup' => [
            'driver' => 'sqlite',
            'database' => base_path().'/tests/_data/stubdb.sqlite',
            'prefix' => '',
        ],

        'testing' => [
            'driver' => 'sqlite',
            'database' => base_path().'/tests/_data/testdb.sqlite',
            'prefix' => '',
        ],

Then in my config\testing\database.php file looks like this

return [
    'default' => 'testing',
];

Then I make a script file (personally I call it d.sh - but call it whatever you want). This script populates the databases and keeps them in sync

composer dump
php artisan migrate:refresh --seed
rm tests/_data/stubdb.sqlite
rm tests/_data/testdb.sqlite
touch tests/_data/stubdb.sqlite
php artisan migrate --env=testing --database=testingsetup

Finally, in TestCase.php I put this

public function setUp()
    {
        parent::setUp();

        exec('cp tests/_data/stubdb.sqlite tests/_data/testdb.sqlite');
    }

This means inbetween each test, you get a new clean empty database. I then use Laracasts\TestDummy to populate specific items in each test that I want.

You'll notice I am not running the migrations within the test suite - there is no need, and thus speeds up the tests.

Works perfectly, is very fast, and you only need to set this up once per application. Takes about 90secs and then you good to go.

3 likes

Please or to participate in this conversation.