Skip to content

Cover dbtest's infrastructure-failure branches behind a testing.T interface #19

Description

@jbrahy

Follow-up from #6, which was closed with this explicitly left open.

internal/dbtest is the lowest-coverage package (~66%). Every remaining uncovered line in SetupDB is a t.Fatalf branch that fires only when MySQL breaks mid-call: CREATE DATABASE fails, the fresh pool cannot ping, migrations fail against a database created a moment earlier.

Those cannot be reached today, because triggering them means the helper fails its own test.

The approach

Introduce a narrow interface over the testing.T methods SetupDB actually uses:

type testingT interface {
    Helper()
    Skipf(format string, args ...any)
    Fatalf(format string, args ...any)
    Logf(format string, args ...any)
    Cleanup(func())
}

Keep SetupDB(t *testing.T) *sql.DB as the public signature so no caller changes, and have it delegate to setupDB(t testingT). Tests then pass a fake that records calls instead of aborting.

The one subtlety: real Fatalf calls runtime.Goexit(), so a fake has to stop execution somehow — panic with a sentinel and recover in the test is the usual approach. Get that right or the tests will pass for the wrong reason.

To actually trigger a CREATE DATABASE failure you will likely want a privilege-restricted MySQL user (GRANT SELECT ON *.* only). That is why this was not done inline: it couples the suite to environment setup, including CI. Worth doing if you can keep the coupling contained — e.g. skip those specific tests when the restricted user is absent, rather than requiring it everywhere.

Why it matters

SetupDB is called by every database-backed test in the repo. Its failure paths are the ones that decide whether a broken environment is reported or silently skipped — and there is prior art for getting that wrong here: SetupDB used to skip under CI, which meant a wrong DSN produced a green run that exercised no SQL at all (fixed in 6d82e77).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:backendGo / MySQL sidegood-first-issueSmall, well-scoped, no deep system knowledge required. Start here.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions