# Test conventions (plan 10-workflow-example.md, section 6.3) Integration tests only. Every test exercises a URL end to end through real HTTP handling, routing, middleware, views, and services. Isolated unit tests are forbidden. ## Placement Test file path and name derive from the URL under test; exactly one structured place per route: | Route | Test file | |---|---| | `/health` | `tests/example/health_test.cpp` | | `/users/:id` | `tests/example/users/id_test.cpp` | | `/orm/users` | `tests/example/orm/users_test.cpp` | Shared helpers live in `tests/example/support/` and are not tests. ## Case template Every test file follows Arrange / Act / Assert: ```cpp // Route: GET /orm/users (one-line behavior note) #include "support/Assert.hpp" using namespace molo::example::test; int main() { Fixture f; // Arrange: seed via app API auto res = f.client->get("/orm/users"); // Act: one HTTP request check(res.status == 200, "status 200"); // Assert: status ... check(contains(res.body, "\"rows\""), "body shape"); check(!f.services.sqlite->tables().empty(), "side effect: table exists"); return finish("orm/users"); // names the route, never silent } ``` Every route needs at minimum: happy path, auth failure (or 404/405 when the route has no auth), validation failure, and one limit case (body too large, rate limited, or not found). ## Rules - Seed through the app API, never direct service writes, unless the test targets self-healing. - Assert status code, content-type, body shape, plus one side-effect check (DB row, metric emitted, listener ran, file listed). - Loud skips: if a fixture or the environment cannot be verified, fail with a clear reason and counter. Never silently pass. - Fixture services reset per test binary (fresh `Fixture` per main); never share state across files. - Caps: full suite max 10 min; single test max 30 s. Zero tolerance for flakes: quarantine plus spec gap entry, fix within one session. ## Running ```sh make -f example/example.mk example-test # this part, standalone make test # whole repo (root Makefile) ``` Each binary prints `ok:` lines and ends with `PASS: ` or `FAIL: (N failures)` with a nonzero exit.