3

From the Laravel Testing Documentation:

# Parallel Testing & Databases
Laravel automatically handles creating and migrating a test database for each parallel process that is running your tests. The test databases will be suffixed with a process token which is unique per process. For example, if you have two parallel test processes, Laravel will create and use your_db_test_1 and your_db_test_2 test databases.

How do I configure this?

I have my testing .env set to an arbitrary database name test_db and when I run a test that uses the Illuminate\Foundation\Testing\DatabaseMigrations trait, I get the following error:

Illuminate\Database\QueryException: SQLSTATE[HY000] [1049] Unknown database 'test_db' (SQL: drop database if exists test_db_test_1)

How does the migration trait know what database name to use for prefixing the test databases it creates?

Joel Mellon
  • 3,672
  • 1
  • 26
  • 25

1 Answers1

3

Although it's not documented, it's apparent that Laravel uses the DB_DATABASE var's value as the prefix for its parallel test DBs.

I was hesitant to use my existing DB name as my test env DB since I don't want to forget the --parallel switch and destroy it (even if it's just in my local environment).

Unfortunately, a random DB prefix cannot be used unless that database exists already. So if you want parallel to create test_db_test_1, and test_db_test_2, you need to already have test_db created.

I see three options to avoid setting the env DB to the app DB:

  1. Create the test database ahead of time, as mentioned above. (This is probably the best bet for pretty much everyone.)
  2. Leave your testing env variable as your app database and make sure to run artisan testing with --parallel. I hate this!
  3. Set your testing env's DATABASE_DB to null/blank.

With option #3 when running in parallel, and using the DatabaseMigrations trait the app connects to the DB without specifying the database name (so it doesn't fail connecting) then it creates the test databases without prefixes, so you'll end up with _test_1, _test_2, etc.

Although it's apparent that simply creating a test DB ahead of time is the best option, I hoped for a solution that would automatically create and drop databases for testing. I was looking for the functionality of SQLite but with MySQL or Postgres since I need features that SQLite doesn't support.

There doesn't appear to be an out of the box solution for this, except with option #3, which isn't great for a couple of reasons. You always have to run --parallel although forgetting it doesn't break anything.

Also, test failures often leave the temp DB(s) in place so test databases are often sitting around taking up disk space until the next run drops them, unfortunately. None of these solutions really get me ephemeral test DBs.

I'll most likely end up writing raw queries to create databases using PHPUnit test event listeners.

Joel Mellon
  • 3,672
  • 1
  • 26
  • 25