2 min read

Use MySQL on Github Actions for Laravel Pest Testing

If you don’t use SQLite in production, you shouldn’t use it in testing or CI/CD either.

This is one of the reasons why I switched from using the SQLite + :memory: combo for my Laravel + Pest testing:

// migration
Schema::create('segments', function (Blueprint $table) {
    $table->id();
 
    $table->uuid('uuid')->unique();
 
    $table->string('name')->unique();
 
    $table->timestamps();
 
    $table->softDeletes();
});
 
// route
Route::get('/segments', function (Request $request) {
    $value = $request->input('search');
 
    return Segment::query()
        ->when($value, function (Builder $query, string $value) {
            $query->where('namexxx', 'LIKE', "%$value%")
        })
        ->get();
});
 
// test
it('can search', function () {
    get(uri: '/segment?search=awesome')
        ->assertStatus(status: 200);
});

Notice how I intentionally wrote the wrong field name in the search query. Surprisingly, my tests still pass. It should throw an \Illuminate\Database\QueryException as it would in a browser.

 PASS  Tests\Feature\Segments\IndexControllerTest
 it can search

According to the SQLite documentation:

If a keyword in double quotes (ex: “key” or “glob”) is used in a context where it cannot be resolved to an identifier but where a string literal is allowed, then the token is understood to be a string literal instead of an identifier.

So what we need to do is to use real database for testing, specifically MariaDB in my case. You’ll need to modify your phpunit.xml first.

phpunit.xml
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
<env name="DB_CONNECTION" value="mysql"/>
<env name="DB_HOST" value="testing-host"/>
<env name="DB_DATABASE" value="testing-db"/>
<env name="DB_USERNAME" value="testing-username"/>
<env name="DB_PASSWORD" value="testing-password"/>

Adjust this configuration according to your needs. If left blank, Laravel will fallback to defaults, such as DB_USERNAME being forge.

Next, modify your GitHub action. Add your preferred database image into services, next to container:

jobs:
  pest:
    runs-on: ubuntu-latest
 
    container:
      image: serversideup/php:8.1-cli
 
    services:
      mariadb-testing:
        image: mariadb:10.11
        env:
          MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true
          MARIADB_DATABASE: testing

Again, adjust the env settings to match your phpunit.xml.

That’s it, now your github action will run tests against a real database instead SQLite.