Database Testing

Database Testing and RefreshDatabase

RefreshDatabase runs migrate:fresh once per run, then wraps each test in a transaction that is rolled back, so every test starts empty. Factories (Defining Model Factories), such as Product::factory()->outOfStock()->count(3)->create(), fill the tables, and assertDatabaseHas(), assertDatabaseMissing() and assertDatabaseCount() check the result.

SQLite 4,756 hides bugs that MySQL 524 's strict sql_mode and collations catch (SQL Modes and Strict Mode and Character Sets and Collations), so run the suite on MySQL too. Adding MySQL settings to .env.testing changed nothing: the suite still took 0.45 s on SQLite. PHPUnit 79,198 sets the <env> values in phpunit.xml first, and dotenv never overwrites a variable that already exists. The two lines had to go:

Pointing the tests at a MySQL test databaseShell
cat .env.testing           # DB_CONNECTION=mysql, DB_DATABASE=shop_test, user and password
sed -i -e '/name="DB_CONNECTION"/d' -e '/name="DB_DATABASE"/d' phpunit.xml
php artisan test --compact
Output
  Tests:    11 passed (36 assertions)
  Duration: 1.97s

Afterward shop_test.products was empty, since every test had rolled back. For Dusk 1,946 , whose browser cannot see an open transaction, use DatabaseTruncation. With brianium/paratest, php artisan test --parallel gives each process its own database (shop_test_1, shop_test_2).