Files

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:

// 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

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: <route> or FAIL: <route> (N failures) with a nonzero exit.