harness-testing
Skill1 starsChanged 50 days agoMITView on GitHub
Use when writing, designing, or strengthening harness tests: tests that boot a larger unit of a system (an HTTP handler, a job, a UI flow) into a realistic but controlled environment (fake requests, mocked services/APIs, controlled env vars, an in-memory/seeded database, fake timers) and assert end-to-end behavior. Use when asked to \"test the whole handler\", \"integration test without a real DB/network\", \"mock the services and run the real code path\", \"add a test harness\", or to improve reliability of code that only misbehaves when wired to its dependencies. Framework-agnostic; includes notes for TypeScript/Deno/Node, Python, and Go.
In this repository21 other files it gives its agents.
- a11y-auditSkill
- agentic-peer-reviewSkill
- changelog-to-videoSkill
- cinematic-hyperframesSkill
- code-cleanupSkill
- endpoint-surface-mapSkill
- field-web-performanceSkill
- french-accountingSkill
- google-ai-seo-fundamentalsSkill
- google-ai-seo-optimizationSkill
- ground-truthSkill
- impossible-by-designSkill
- legacy-code-reviewSkill
- merchant-feed-auditSkill
- merge-time-ci-economicsSkill
- postgres-privilege-auditSkill
- provider-canarySkill
- repo-wide-dead-code-sweepSkill
- security-hardeningSkill
- website-ai-agent-readinessSkill
- youtube-video-editingSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 4 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 18
Use it for behavior that only appears when code is wired up: auth and status codes, payload assembly, branching, persistence, retries, …
- Distinctive: line 22
If the project already has a harness toolkit, its names, options and known pitfalls win over the illustrative ones below: read its source …
- Distinctive: line 28
Never change production code to make it testable: No dependency-injection refactors, no "export the handler just for tests", no test-only …
- Very specific: line 106
Seed lazily, tear down completely: Read seeded data at execution time so tests arrange before acting.
- Very specific: line 119
Fast, separate, gated: No real I/O. Name harness tests distinctly (e.g.
- Very specific: line 137
When a harness covers payments, refunds, compensation, labels or any durable provider operation, read references/provider-recovery.md: …
- Distinctive: line 165
Stop the stack without a backup, and delete the test secrets and any seeded users.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Harness Testing
A harness test runs your real code inside a wrapper that simulates the runtime just enough to verify behavior: fake inputs, mocked services, controlled env, a seeded in-memory database, fake timers, and setup/teardown. Instead of testing one function in isolation, you plug a larger unit (a request handler, a worker, a screen-level flow) into a realistic-but-controlled environment and assert what it actually does.
Use it for behavior that only appears when code is wired up: auth and status codes, payload assembly, branching, persistence, retries, error handling. Keep pure-logic unit tests for isolated helpers.
Start from the project's own harness
If the project already has a harness toolkit, its names, options and known pitfalls win over the
illustrative ones below: read its source and one existing harness test before writing a new one. A
project that vendors this skill may keep that map in references/project.md next to this file; when
the file exists, read it first.
The one rule: non-invasive
Never change production code to make it testable. No dependency-injection refactors, no "export the handler just for tests", no test-only flags in shipped code. A harness that demands production changes isn't riskless and won't be adopted for the code that matters most. Intercept a seam instead (below). If you genuinely cannot reach a seam without touching production, that's a design finding to raise, not a reason to weaken the rule.
Step 1: Find the one seam
A harness is only as simple as its interception point. Find the single boundary that every external dependency crosses, and mock there, not once per dependency.
- Outbound network is usually the seam: most SDKs (DB clients, payment, email, storage) ultimately
call the platform's HTTP primitive. Intercept that and you mock them all with one mechanism.
- TypeScript/Deno/Node: replace
globalThis.fetch(verify your SDKs use it; many do in modern runtimes), or usenock/msw. - Python:
responses/respx, or monkeypatchrequests/httpx. - Go: inject an
http.RoundTripper/httptest.Server.
- TypeScript/Deno/Node: replace
- The entrypoint is the other seam: capture the handler the framework would serve, and call it
with a fake request, without starting a server. (E.g. intercept the serve call to grab the handler
closure; build a fake
Request; assert on the returnedResponse.) - The data client, for a UI flow. A screen-level test replaces the one data-client module the app imports (a module mock) with a chainable fake over seeded tables, then renders the real component inside the real router and providers. Real component, real hook, real query code; only the client is fake.
- The clock: swap in fake timers so time-dependent logic (timeouts, retries, TTLs) is deterministic.
One seam = one mental model. Resist per-dependency mocks; they drift and multiply.
Step 2: Build the harness toolkit
Small, composable, single-purpose pieces. The names follow one reference implementation; a project's own toolkit keeps its names.
loadHandler(module): boot the real handler (intercepting the entrypoint, not editing it) and throw if nothing was captured.fetchRouter(routes): matchmethod + url → canned response, record every call (method, URL, body and headers: an idempotency key or an account header is often the whole correctness of a call), and throw on anything unmatched.storeRoutes(seed): translate an in-memory dataset into the responses the data layer expects; record writes so tests can assert persistence.withEnv(vars): snapshot, set, and restore environment variables.makeRequest(...): build fake inbound requests.createHarness({...}): wire the above plus fake timers, exposerequest()and the recorders, and register onerestore().
Order the routes from specific to generic: scripted overrides (stored procedures, a refused call, a recovered operation) first, then the generic store routes, then external services. A generic store route placed first answers calls it was never meant to model.
Step 3: Write the test
Arrange (env + seed + routes) → boot the real unit → act (one fake request / one render) → assert on
the real output and the recorded outbound calls → restore() in finally.
// Illustrative (TypeScript). Adapt the seam to your stack.
const h = await createHarness({
module: new URL('./checkout/index.ts', import.meta.url).href, // booted, not modified
env: { SERVICE_KEY: 'test', API_BASE: 'https://api.payments.test' },
db: { tables: { orders: [], items: [{ id: 'i1', price: 100 }] } },
routes: [{ method: 'POST', url: 'https://api.payments.test/charges', respond: () => json({ id: 'pay_1' }) }],
fakeTime: Date.parse('2026-01-01T00:00:00Z'), // pinned at construction
});
try {
const res = await h.request({ method: 'POST', url: 'https://fn.local/checkout', body: { itemId: 'i1' } });
expect(res.status).toBe(200);
expect(h.db.tables.orders).toHaveLength(1); // persistence
expect(h.fetchCalls.some((c) => new URL(c.url).hostname === 'api.payments.test')).toBe(true); // outbound
} finally {
h.restore();
}Principles (the difference between a harness that helps and one that lies)
- Boot the real thing. Mock dependencies, never the unit under test. The value is exercising real code against fakes, not re-implementing its logic in the test.
- Loud unmatched, never silent. An unhandled dependency call must throw with a clear message,
not return
undefinedor hang. Silent gaps produce green tests that assert nothing. The same holds inside the fake store: a filter operator it does not understand must fail, because a dropped filter matches more rows than production would. - Seed lazily, tear down completely. Read seeded data at execution time so tests arrange before
acting. One
restore()reverts every global you touched (network, entrypoint, env, timers) in reverse order; call it infinally. Cross-test leakage is the #1 harness failure mode. - Derive assertions from the contract. Establish expected behavior from requirements, protocol contracts or independently verified examples before reading the implementation's result. Record surprising observations separately as characterization evidence; do not turn a defect into the expected outcome merely because the current code produces it. Fix confirmed defects within the authorized scope and preserve a failing-before/passing-after reproduction.
- Keep the fake minimal; extend on demand. Emulate only the verbs the unit uses. A smaller fake is easier to trust. Add a verb deliberately when a test needs it; never loosen matching to pass.
- Own only what you can clean up. Real clients start background work (refresh timers, pools) the unit never disposes because the runtime tears it down. Disable leak/resource sanitizers for harness tests specifically rather than editing production to satisfy a detector.
- Fast, separate, gated. No real I/O. Name harness tests distinctly (e.g.
*.harness.test.*) so the unit suite stays quick, and fold them into the one verification command the whole team and every agent runs, so they're backpressure that rejects regressions, with CI as the mechanical ratchet. - Pin the clock when you build the harness. A fake clock that starts at the real time and refuses to move backwards accepts a pinned instant assigned later only until that instant is in the past, then fails. Pass the instant to the constructor; move the clock forward mid-test only.
- Know what the fake store cannot see. An in-memory store has no column defaults, no schema, no grants, no constraints and no triggers. A row inserted without a defaulted column stays without it, so a later filter on that column silently matches nothing; a read naming a column that does not exist passes; a single-row read or update of zero rows may error where the real API returns null. Emulate the default or the stored procedure explicitly in the test, and prove the real behavior once against a real database (see the runtime section).
- Match hosts by parsing, never by substring. Filter recorded calls with
new URL(url).hostname === 'api.example.test'. A substring also matches a query string, and static analysers such as CodeQL flag the substring form in test code too.
Money, provider recovery and database evidence
When a harness covers payments, refunds, compensation, labels or any durable provider operation, read
references/provider-recovery.md: internally consistent provider
fixtures, recovery reads, provider success followed by local failure, conservation at the boundaries,
real database evidence and a separate provider Sandbox check.
When the behavior depends on the runtime
A harness proves the handler's logic against seams you control. It cannot prove what only the runtime
or the real database provides: grants, whether a client that hangs up aborts req.signal, what a
gateway flag does to an opaque bearer, how a lease behaves when its holder dies. A harness that
simulates such a primitive passes whether or not the runtime implements it. On one local edge runtime
a disconnected client's request was never aborted, so a claim release built on that passed its
harness test and failed live. When a design rests on runtime behavior, run it:
- Use a disposable stack, never the running one. Copy the project's local stack configuration, give the copy its own project id and its own ports, and pass its directory explicitly to every command. A reset aimed at the wrong project wipes someone else's data.
- Replay every migration, run the database test suite, and serve the real handlers with test-only secrets. Re-copy the configuration after changing a function's flag: a stale copy reproduces the old gateway.
- Probe a privileged handler live once. A harness has no grants, so a handler that reads or
writes a table directly under a service role is unproven until it runs for real: create a test user
through the auth admin API, obtain a real token, call the served function, and read the rows back.
Twenty-three green harness tests once hid a
permission deniedthat only this probe showed. - Drive the real caller (the worker,
curl), read rows back in the database container, and stop processes the way production does (SIGTERM, a dropped connection) before checking what is still claimed. - Mutation-test the SQL guards on that database: redefine one function without its guard, rerun the database test, expect a named failure, then restore the definition.
- Stop the stack without a backup, and delete the test secrets and any seeded users.
Anti-patterns
- A test that passes whether or not the code under test runs (over-mocked, asserts nothing real).
- Editing production code "just a little" for testability: start over from a seam.
- A bespoke mock per dependency: collapse to one seam.
- Matching
*/ catch-all routes everywhere: fine for a "did it reach real work" smoke, but specific routes are what let you assert the right calls happened. - A stored procedure left unscripted and answered by a generic table route, which reads the procedure path as a table name and acknowledges the call as an ordinary write.
Background reading
Anthropic: Harness Design for Long-Running Apps; Effective Harnesses for Long-Running Agents.
OpenAI: Harness Engineering. Geoffrey Huntley: Ralph Wiggum as a Software Engineer.
celesteanders/harness: docs/best-practices.md.
See references/checklist.md for a copy-pasteable pre-flight checklist.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

