Testing Standards

This is the standard the Quality Gate's Reliability lens holds work to for testing. It expands the one line the Coding Style Guide carries β€” "TDD SHOULD be used" β€” into a working standard: what to test, how, where it runs, and how we tell a genuinely healthy suite from one that merely goes green. It builds on the Infrastructure Planning Policy (which measures delivery with DORA and runs CI/CD from the reviewed main line). Deviations are allowed, but β€” as everywhere in the handbook β€” they must be deliberate and justified in the project's design notes.

Testing is where OSBR's values become executable. Be Nice: a test is the clearest documentation a teammate or future maintainer will read, so every one describes a behaviour in plain terms. Be Kind: a red or flaky CI on main blocks everyone, so keeping the suite fast, green, and honest is a duty owed to the team, not a personal preference. Be Strong: tests exist to find the failure before a user does, so they must run against the real thing and target the conditions most likely to break. Humans and AI agents write tests here as collaborators β€” and that partnership carries a specific hazard this policy names head-on (Β§3-14).

How to read this policy

1. Goal

The goal of testing at OSBR is fast, trustworthy evidence that the system does what it should β€” and keeps doing it as it changes. Concretely:

A test that does not move one of these goals is waste. We optimise for evidence, not for a number on a coverage badge (Β§3-11).

2. Responsibility

3. Practices

3-1. Test early, as footholds β€” and against the real thing

Write tests from early development, not as a post-hoc chore. Early tests are footholds: small, cheap checks that pin down behaviour as you climb, so each step stands on solid ground. This is the spirit of Test-Driven Development (Beck) β€” the pure core described in Style Guide Β§3-5 is testable without mocks, so there is little excuse to defer.

3-2. Shape of the suite β€” Pyramid and Trophy

OSBR does not mandate a single silhouette; it mandates a deliberate one. Two named models bound the sensible choices:

Rules that hold under either shape:

3-3. Test sizes β€” classify by cost, not just by layer

Adopt the small / medium / large taxonomy (Google) to describe what a test is allowed to touch, independent of what layer it targets:

Size is about isolation and speed, and it maps directly to where a test runs (Β§3-12). Label or fold the sizes into the suite so CI can run small tests on every push and gate the slower tiers appropriately.

3-4. Coverage of intent β€” one behaviour-describing test per public function

3-5. Target boundary conditions over test count

3-6. Domain-layer regression tests β€” parameterized, faked, kept green in CI

The domain layer is where OSBR's value lives and where regressions hurt most. It is also, by the hexagonal design in Style Guide Β§3, the layer with no real IO β€” so it is cheap to guard densely.

3-7. Integration tests against real dependencies

Mocks encode what we believe a dependency does; real dependencies encode what it actually does. For the code that crosses a boundary β€” repositories, HTTP clients, migrations, queries β€” the belief is exactly the thing under test.

3-8. Contract testing across service boundaries

When two services are developed and deployed independently, integration tests on each side can both pass while the two disagree about the wire format. Contract testing (Pact) closes that gap: the consumer declares the interactions it needs, and the provider is verified against that contract in its own pipeline.

3-9. Property-based testing for input-heavy logic

Example-based tests check the cases the author thought of. Property-based testing (fast-check for TypeScript, Hypothesis for Python) checks invariants against hundreds of generated inputs, including the awkward ones no human enumerates β€” and shrinks any failure to a minimal reproducing case.

3-10. When to mock, deliberately

The two schools of TDD are a tool-selection guide, not a tribe to join:

Rule: reach for a mock only at a true seam β€” an expensive, non-deterministic, or side-effecting boundary. Mocking a collaborator that owns real logic produces the tautological green tick of Β§3-1. When in doubt, prefer a fake over a mock.

3-11. Coverage is a metric; mutation testing checks the tests

3-12. Where tests run β€” local-agnostic vs CI production-simulating

Where a test runs follows from its size (Β§3-3) and from OSBR's CI/CD stance (deploy from the reviewed main line, dev/staging/prod at parity β€” see the Infrastructure Planning Policy):

3-13. Flaky tests are quarantined, not ignored

A test that passes and fails without a code change is worse than no test: it trains the team to ignore red. Be Kind to everyone downstream of a flaky main.

3-14. "Many AI-generated tests pass" is not a healthy codebase

OSBR embraces human ⇄ AI cooperation, and agents are productive at generating tests. That productivity carries a specific trap: a large, green, AI-generated suite can look like health while proving almost nothing. Generated tests skew toward happy-path assertions, toward asserting on mocks the same agent wired up (Β§3-1), toward restating the implementation rather than the intent, and toward volume over boundaries (Β§3-5). A thousand such tests passing is not evidence the system works.

Therefore, for AI-generated tests specifically:

References

Test-driven development & schools

Suite shape

Techniques & tools

Coverage & flakiness

Related OSBR standards