A platform this size, run by one person, has one hard question underneath it. How does it keep working when there is no test team behind it? The answer is numerous test suites. Three of them carry the weight. Each of the three checks exactly one thing, and never the thing another one checks. The first checks that the logic works. The second checks that the whole flow holds against a real database. The third checks that the right people, and only the right people, can reach each endpoint. Each is its own suite. No test lives in two of them.
Each of the three checks exactly one thing, and never the thing another one checks.
The first suite tests logic in isolation. A function, a component, a piece of pure behavior, with no database and nothing else running. These are the fast tests, the ones that finish in seconds on every change, because there is nothing to stand up and nothing to tear down. That speed is the point. A suite that runs in seconds can run on every save. A test that runs on every save catches a regression in the minute it is written, not the hour it is later debugged. Each unit test answers one thing only. Given this input, does this code return the right output. When a unit test goes red, a function regressed. The search stops there.
The second suite tests the whole flow. A real request goes into the running server, through the real routing and the real handlers, out to a real database. The result comes back to be checked against what should have happened. This is the slow, heavy suite. It stands up actual infrastructure for every run, a live server talking to a live Postgres, which costs seconds where a unit test costs milliseconds. It earns that cost by catching what unit tests cannot see. A function can be correct in isolation and still be handed the wrong input, called in the wrong order, or wired to a route that never reaches it. Unit tests, by design, never look past the function. Integration is where the seams between correct pieces are checked. The seams are where real systems break. When it goes red, a flow came apart, not a function.
The third suite is the one most codebases never build as a suite at all. It tests access control. It is the reason the other two are not enough.
The most expensive bug a multitenant platform can have is one tenant reaching another tenant's data. That is exactly the bug ordinary tests are worst at catching, because it does not look like a bug. It is a valid request, correctly formed, from the wrong person. The logic works. The flow holds. The only thing wrong is who is asking.
Every protected route already declares the permission it requires, stated in the route itself. A generator reads those declarations, together with the table of which role holds which permission, and produces a test for every route and every role. On a platform with hundreds of protected routes and several roles apiece, that is a matrix no person keeps current by hand. Each generated test makes a real request as one role and confirms it reaches exactly what it is entitled to and nothing more. The tests come from the same schema that generates the rest of the platform's typed surfaces. They never have to be kept in sync. A new protected route arrives already tested, its access checks written by no one. When the permission a route requires changes, the test that guards it changes with it on the next generation.
That is the piece that stands in for a QA team on the surface that most needs one. A person hand-writing a permission test for every route and every role would fall behind in the second week. The day they fall behind is the day a permission changes with no test to notice. Because the coverage is generated from the permission rules rather than kept in step with them by hand, it cannot fall out of step. It is those rules, run as tests. And where a route cannot be set up for a test, the generator records the gap with a reason instead of skipping it in silence. The holes show up in the output rather than hiding in it.
The three suites are held apart by the build, not by discipline. Each has its own place in the tree, its own configuration, and its own job in the pipeline. Each configuration takes in only its own files and shuts out the others. The unit suite runs without a database and in parallel, because it needs no database and has no turn to wait for. The integration and access suites run against the live database one at a time, because a shared database cannot be handed to two tests at once. The suites are that different in shape. The build keeps them that separate. A test file belongs to exactly one suite. There is no way for it to belong to two.
That separation buys what a solo builder needs most, a fast read on what broke. A red build is not a mystery to sit and stare at. If unit is red, a function regressed. If integration is red, a flow came apart. If access control is red, a permission boundary moved. The suite that fails names the kind of failure. The search for the cause starts already narrowed to one layer. Running every check against everything would be slower and would say less, because a failure that could have come from anywhere points nowhere. Three suites that each check one thing, and never the same thing, point straight at the break.
What it checks
Logic in isolation
The whole flow, end to end
Who can reach each route
Database
None
Real Postgres
Real Postgres
Speed
Milliseconds, in parallel
Seconds, one at a time
Seconds, one at a time
Written by
By hand
By hand
Generated from the route permissions
None of this is testing for its own sake. It is what lets one person put an autonomous, multitenant platform in front of real businesses and trust it between deploys. The logic is checked, the flows are checked, and the access rules are checked on every change, the last of them generated from the same source the platform itself is built from. The rigor a team would provide by hand comes from the build instead, the only way one person could have it at all.
And it is what makes the rest of the platform possible. A system built to run on its own, to draft and publish and act without a person watching each step, is only as sound as the tests standing behind it. Autonomy without verification is a liability, not a feature. The three suites are that verification. And because the access suite is generated from the rules it checks rather than maintained by hand, it is the one that stays trustworthy on the surface where a mistake is most expensive, the line between one tenant's data and another's.
If you're interested in my work or Giant Context, contact me!