Skip to content

Built a layered automated test suite — 981 Go tests, 543 frontend and browser specs, 494 SQL behavioural tests — with mutation testing, property‑based tests and an accessibility gate.

Situation. A platform that keeps its business logic in the database has a testing problem most projects do not. The logic is not in the language the test framework is good at — it is in SQL, behind function boundaries, and SQL is exactly the sort of code that goes untested because testing it is awkward. Add a Go API and a Next.js frontend on top of that, and “the important parts are covered” quietly turns into “the parts that were easy to cover are covered.”

Task. Each layer needed its behaviour checked where that behaviour actually lives, rather than everything being checked from the outside through a browser.

Action. Four layers got four kinds of test. The Go API carries 981 test functions across 310 files. The frontend carries 543 Vitest and Playwright specs, including 48 end‑to‑end files and 30 browser specs. The database carries 494 behavioural test files — 116,876 lines of SQL asserting through 6,654 raised exceptions — so a stored function is tested in the database instead of through three layers of application above it. Above those sit the tests that test the tests: Stryker mutation testing deliberately breaks a line and fails when nothing notices, and fast‑check generates inputs nobody thought to write down. An axe‑core gate asserts zero WCAG 2.0 and 2.1 A and AA violations, which makes accessibility a build failure rather than an audit finding months later. Coverage thresholds only ever move upward. The whole suite runs as 10 jobs in a 612‑line workflow.

Result. Changing something structural stopped being frightening, which is the only thing that keeps a codebase this size from calcifying. The honest cost is time — the suite is slow, it taxes every change, and at this size it needs maintenance of its own. What it buys is the ability to keep moving quickly, and that is worth more than the minutes it takes.