test-reliability
Skill2 starsChanged 27 days agoMITView on GitHub
Design, review, and diagnose tests and fixtures that can fail nondeterministically under CI concurrency, shared host resources, clocks, process-global state, subprocesses, network listeners, or asynchronous teardown. Use when adding or changing tests with those risks, investigating flaky CI, or reviewing test isolation; use pre-push-checks separately to select outgoing commands.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- petrkindlmann/qa-skillstheir own version, first seen Oct 25, 2026
- fishzjp/qa-skillstheir own version, first seen Oct 21, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- petrkindlmann/qa-skills★ 209same name
- fishzjp/qa-skills★ 62same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository17 other files it gives its agents.
- agent-experienceSkill
- agent-notesSkill
- code-reviewSkill
- docs-standardSkill
- error-handlingSkill
- find-simplificationsSkill
- lifecycle-reviewSkill
- perf-evidenceSkill
- pre-push-checksSkill
- prose-standardSkill
- record-browser-gifSkill
- responsive-uiSkill
- stacked-prsSkill
- trim-cot-leakageSkill
- ui-ux-reviewSkill
- upgrade-guideSkill
- vibe-harness-bootstrapSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
16 rules. About 0 are common, 15 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈15
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 28
Do not serialize an entire suite because one fixture lacks isolation.
- Distinctive: line 32
Use the resource owner's allocator instead of checking availability and claiming it later.
- Distinctive: line 35
Create private per-test temporary directories with a unique-directory API.
- Distinctive: line 37
Use exclusive creation where a path must not already exist.
- Distinctive: line 38
Keep stable recorded identifiers separate from ephemeral transport addresses.
- Distinctive: line 44
Treat environment variables, the working directory, fake timers, locale and time zone, module mocks, registries, console hooks, globals, …
- Distinctive: line 46
Prefer an injected dependency or instance-local adapter.
- Very specific: line 50
keep an after-each fallback when failure before the local finally is plausible.
- Distinctive: line 55
When CI runs on Windows and POSIX hosts, a value the operating system owns does not always come back the way a test wrote it.
- Distinctive: line 72
Wait for an explicit readiness event, handshake, state transition, owned promise, or externally observable condition.
- Distinctive: line 73
Use deferred promises or barriers to place a race at a deterministic point and prove the operations overlap.
- Distinctive: line 74
Use a timeout only to bound a wait, never as the condition that makes the assertion correct.
- Distinctive: line 75
Do not assert scheduler-dependent ordering unless that ordering is the product behavior under test.
- Distinctive: line 76
When time itself is the subject, inject or fake the clock and always restore real timers.
- Distinctive: line 89
Verify external state, events, files, logs, exits, or disposal instead of trusting the component's self-report.
- Distinctive: line 95
Do not present these as root-cause fixes: increasing a timeout without identifying the awaited state.
≈ “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
Reliable tests under real CI topology
Build tests that remain correct under the project's real CI topology, not only when run alone on a quiet workstation. This skill owns isolation and reliability decisions; it does not replace the project's test-tier policy or select every command for a push. It is guidance, not a checklist.
Read the owning rules
- The project profile (
.agents/project-profile.md) for test commands and the evidence each surface requires. docs/defensive-patterns/for lifecycle, subprocess, cancellation, and teardown behavior.- The active test-runner configuration and CI workflow when their worker or job topology affects the test.
- pre-push-checks, after the test design is sound, to select outgoing validation.
Model the execution topology
Assume these layers can overlap unless the active configuration proves otherwise:
- Tests in one file.
- Separate test files or worker processes.
- Independent test-runner or check processes in one CI job.
- Different CI jobs whose runners share one host.
Process isolation does not isolate host ports, predictable filesystem paths, external services, databases, sockets, or inherited child processes. For every acquired resource, identify its owner, atomic allocation mechanism, observable readiness signal, registered cleanup, and quiescent completion signal.
Do not serialize an entire suite because one fixture lacks isolation. Narrow the exclusive scope or change the resource allocation first. A sequential block inside one file cannot protect a host resource from another file, process, job, or runner.
Allocate resources atomically
Use the resource owner's allocator instead of checking availability and claiming it later.
- Network fixtures bind loopback with port 0 and read the assigned address only after the server reports that it is listening. Never scan for a free port and bind it later.
- Create private per-test temporary directories with a unique-directory API; do not acquire predictable shared paths.
- Give shared databases, sockets, sessions, and output locations unique per-test namespaces.
- Use exclusive creation where a path must not already exist.
- Keep stable recorded identifiers separate from ephemeral transport addresses; translate inside the fixture instead of forcing the live resource to use the recorded value.
Literal paths and URLs used only as parser inputs or expected values are not acquired resources.
Contain process-global state
Treat environment variables, the working directory, fake timers, locale and time zone, module mocks, registries, console hooks, globals, and global network interception as exclusive mutable resources.
Prefer an injected dependency or instance-local adapter. When mutation is required:
- capture whether the original value was absent or present, and restore that exact state;
- register restoration immediately, with
try/finallyaround the smallest mutation scope; - keep an after-each fallback when failure before the local
finallyis plausible; - intercept the narrowest exact request or call the fixture owns.
Respect platform-owned semantics
When CI runs on Windows and POSIX hosts, a value the operating system owns does not always come back the way a test wrote it.
- Writing a value back is safe only when the assertion tolerates the write-back failing. Restoring a file's modification time to prove a fingerprint invalidates anyway holds everywhere; restoring it to prove a record stays valid assumes a lossless round trip that NTFS's 100-nanosecond ticks do not give a fractional millisecond. Take the expected value from a fresh read.
- Windows matches environment variable names case-insensitively, so
http_proxyandHTTP_PROXYare one entry there. - Windows releases file handles asynchronously, so a rename or removal needs a bounded retry sized to the observed contention.
- Windows has no POSIX permission or signal semantics. A case that depends on them takes an explicit platform skip naming the reason, not an assertion weakened everywhere.
Budget timeouts against the lane
A per-suite or per-case timeout overrides the runner's global timeout instead of yielding to it, so a value below the lane's budget lowers what CI already granted. A suite bound by process creation takes the lane budget; a tighter value carries the reason it is tighter. Raise the hook budget with the test budget, because setup and teardown pay the same contention.
Where a timeout is the subject, keep the outer wait far larger than the timeout under test, or load decides which deadline reports first.
Synchronize on state
A fixed sleep is not evidence that setup completed or cleanup settled.
- Wait for an explicit readiness event, handshake, state transition, owned promise, or externally observable condition.
- Use deferred promises or barriers to place a race at a deterministic point and prove the operations overlap.
- Use a timeout only to bound a wait, never as the condition that makes the assertion correct.
- Do not assert scheduler-dependent ordering unless that ordering is the product behavior under test.
- When time itself is the subject, inject or fake the clock and always restore real timers.
Dispose to quiescence
Register cleanup immediately after acquisition so assertion failures also release the resource. Cleanup stops new callbacks or requests, detaches listeners, restores global hooks, terminates owned work, and awaits child exit, server close, or worker termination. Calling abort(), close(), or kill() without awaiting the completion signal is incomplete teardown. When late completion is possible, prove that disposal prevents it from mutating another test.
Prove the intended regression
- Observe an ordinary regression fail before the fix when practical.
- For a new static or corpus check, temporarily introduce the rejected case and observe the intended failure.
- For a race, use barriers to prove overlap; repeated execution alone is not a race test.
- For ports, sockets, shared paths, or subprocesses, run independent test processes concurrently when cross-process isolation is part of the fix.
- Where a fixture spawns a child with its own deadline, assert that no signal or timeout ended the child before asserting its exit status.
- Verify external state, events, files, logs, exits, or disposal instead of trusting the component's self-report.
Stress runs supplement a deterministic regression; they do not replace one.
Reject flake-masking fixes
Do not present these as root-cause fixes: increasing a timeout without identifying the awaited state; adding retries; making all files serial; swallowing an error or unhandled rejection; weakening an assertion; normalizing away unstable behavior; adding a sleep before cleanup or assertion.
Retries remain valid for documented transient external-provider tests at the external boundary. Restoring a budget the lane already granted, or sizing a bounded retry to measured contention, is not masking.
Diagnose existing flakes
For an existing probabilistic CI failure, follow the CI flake diagnosis workflow. A diagnosis-only request stays read-only: report the cause and evidence unless the user also asks for a fix.
Validate and report
Run the smallest focused regression for the affected behavior, plus topology-specific evidence only when the change owns that risk: restoration evidence for global mutation, quiescent-teardown evidence for lifecycle or subprocess work, concurrent independent-process evidence for ports, sockets, or shared paths, and a negative control for a new check. Report exact commands and observed results; do not describe retries, skipped tests, or pending CI as passing.
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.

