Skip to content
Agentmart
Submit a tool

writing-tests

Write deterministic tests that fail for real product defects.

Skill by caarlos0

IndexedMIT★ 224
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/caarlos0-writing-tests

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Write deterministic tests that fail for real product defects. Use when adding tests, fixing flakes, or reviewing test coverage and reliability.

Use cases: testing, writing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/writing-tests

What's inside

Skill name
writing-tests
Description
Write deterministic tests that fail for real product defects. Use when adding tests, fixing flakes, or reviewing test coverage and reliability.
License
MIT
Instructions
167 lines in SKILL.md · view on GitHub

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Writing Tests

A useful test fails when behavior is wrong, passes when it is right, and
explains the failure without a debugger. Follow repository instructions first.

## Prove the behavior

- Choose the lowest layer that proves the contract: unit for local logic,
  integration for real boundaries, CLI/UI/E2E only for behavior unavailable
  below them.
- Exercise production code. Do not copy its logic into the test or mock the
  unit under test.
- A bug fix needs a focused regression test. Where practical, revert or mutate
  the fix and confirm that exact test fails.
- Assert observable results, not private calls or incidental structure.
- Print expected and actual values, variants, exit status, stderr, and case
  labels needed to diagnose a rare CI failure.
- Cover material success, failure, boundary, default, and state transitions.
  Do not add combinations without a concrete regression risk.

## Control every input

- Inject clocks; fix timezone and locale when formatting matters.
- Seed randomness and print the replay seed on failure.
- Use semantic unordered equality when order is not a contract. Do not hide a
  required order by sorting expected output.
- Give each test an isolated environment, home, working directory, config root,
  database state, cache, and temporary directory.
- Bind servers to port `0` and retain the listener. Never find, close, and
  rebind a "free" port.
- Avoid process-global mutation from parallel tests. Use helpers that restore
  state automatically.

## Synchronize; do not sleep

Replace sleeps and grace periods with a happens-before edge: channel receive,
barrier, latch, event, condition, queue drain, file close, EOF, process exit, or
application readiness.

Use fake time only when time is the contract. Know which clock it controls.
Use a timeout only around an observable wait as an outer deadlock detector;
expiry must fail with diagnostics. Never use a sleep, retry, timeout increase,
or looser assertion as a race fix.

For processes, establish the required order: start output readers, close stdin
when EOF is required, drain stdout and stderr, observe exit, then clean up.
Preserve output even when finalization fails.

## Own resources and cleanup

Register cleanup immediately after acquisition. Teardown in dependency order:
stop producers, cancel work, drain or join consumers, flush, close resources,
then delete storage. Surface cleanup failures.

Parallel tests need separate resources. A shared temp path, port, database row,
clock, fake timer, module cache, or mutable global is a race even if it usually
passes.

Use a local implementation of the real protocol at boundaries: an in-process
HTTP server, transaction-isolated database, or controlled fake implementing the
real interface. Do not put live third-party availability, credentials, mutable
data, or rate limits in required tests.

## Snapshots, properties, and fuzzing

Normalize only fields proven volatile, such as generated IDs or temp roots.
Broad normalization can erase the bug. Golden updates must be explicit and
reviewed.

Use property, fuzz, differential, or metamorphic tests when examples cannot
cover the input space or no simple expected value exists. Retain the minimized
input or seed so every discovery becomes a deterministic regression.

## E2E, browser, CLI, and TUI

Wait for the exact readiness needed by the next action: health response, UI
state, log event, or prompt. Do not use arbitrary sleep or generic network idle.
Prefer user-visible and accessibility-based locators plus retrying assertions.

Control browser, viewport, fonts, animation, and dynamic content for visual
tests. Assert CLI/TUI exit status and relevant stdout/stderr after complete
drain. For AI-backed behavior, assert an objective observable contract, not one
exact natural-language answer unless the text itself is the contract.

## Language mechanics

### Go

- Use `t.TempDir`, `t.Setenv`, `t.Cleanup`, `httptest.Server`, the race detector,
  and shuffled runs where relevant. Record shuffle seeds.
- Process-global environment and working-directory changes are incompatible
  with parallel tests.
- `FailNow` and testify `require` must run on the test goroutine. From handlers
  or spawned goroutines, report errors to the test goroutine and synchronize.
- Use channels and `WaitGroup`; use `testing/synctest` only when supported by
  the repository's Go version.
- Compare maps semantically or sort a copied key set for golden output.

### Rust

- Keep test-only helpers behind `#[cfg(test)]`.
- Use channels and barriers for ordering; use
  `#[tokio::test(start_paused = true)]` for timer behavior. Prefer
  `time::sleep(d).await` over `tokio::time::advance(d)`, which does not wait
  for tasks to be polled and can produce false passes.
- When already present, Loom or Shuttle can explore schedules and Proptest can
  shrink and persist failures.
- Ensure all process pipe owners close so EOF and exit are observable.

### TypeScript and JavaScript

- Always await promise assertions and async timer advancement.
- Restore spies, modules, and fake timers after each test; clearing calls does
  not restore implementations.
- Do not combine process-global fake timers or mutable module state with
  concurrent tests.
- Use Playwright locators and web assertions for readiness.
- For subprocess output assertions, await the `'close'` event, not `'exit'`;
  `'exit'` fires before stdio streams finish flushing.

From caarlos0/dotfiles, MIT.

More from caarlos0/dotfiles

Signals

Stars
224
Forks
12
Open issues
0
Last commit (this folder)
Oct 20, 2026 (7 days ago)
Last release
Oct 1, 2026 (26 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from caarlos0

Cite this page

writing-tests skill. Agent Mart. https://agentmart.dev/skills/caarlos0-writing-tests (last updated 2026-10-24)