When to use this
- New function/endpoint/component just landed without tests.
- A bug fix needs a regression test that fails on the old code and passes on the new.
- Not for retrofitting full coverage onto a legacy file unrelated to the current change -- scope to what changed.
The skill file
Copy this verbatim. It's written in the SKILL.md format (YAML frontmatter + markdown instructions) that Claude Code, and increasingly other agent tools, read directly.
--- name: test-writer description: Write tests for the specific behavior introduced or changed by a diff -- happy path, edge cases the change makes reachable, and a failing-then-passing regression test for bug fixes. Use after code changes, not to backfill unrelated legacy coverage. --- # Test Writer ## For new functionality 1. Identify the observable behavior: inputs -> outputs, side effects, errors raised. 2. Write the happy-path test first. 3. Add edge cases specific to this code: boundary values (0, empty, max), the branches the diff's conditionals introduce, and any input validation the code performs. 4. Match the existing test file's framework, assertion style, and fixture/ setup conventions -- don't introduce a new testing pattern for one file. ## For a bug fix 1. Write a test that reproduces the bug: it must **fail** against the pre-fix code and **pass** against the fix. If you can't make it fail first, you haven't actually captured the bug. 2. Keep the test minimal -- the smallest input that exercises the broken path, not a sprawling integration scenario. ## What not to do - Don't test the language/framework itself (e.g. asserting a getter returns what you just set). - Don't write a test so tightly coupled to implementation that any refactor breaks it without a behavior change -- assert on outputs/ observable state, not internals, unless internals are the point. - Don't skip error-path tests because the happy path is more interesting. ## Output The test file(s), plus a one-line note on what each new test actually proves, so the reviewer can check it lines up with the change.
Installing it elsewhere
The frontmatter/body split above is Claude Code's convention. Here's how to carry the same instructions into other tools:
Save the file below verbatim (frontmatter included) at that path, project-local or in ~/.claude/skills/ for a user-level skill. Claude Code loads the name/description pair to decide when to pull it in, or you invoke it directly as /test-writer.
Convert the YAML frontmatter to Cursor's rule format (description, globs, alwaysApply: false) and keep the markdown body as the rule content. Cursor surfaces it by description match, same idea as Claude Code's auto-load.
Codex CLI (and increasingly other agentic CLIs) read AGENTS.md at the repo root as always-on instructions. Paste the markdown body under a heading like ## {title}; for GitHub Copilot's coding agent, the equivalent file is .github/copilot-instructions.md.
Append the markdown body to .windsurfrules at the repo root. Windsurf treats the whole file as always-on context, so keep only the instructions you want applied on every request.
- Writing a test that passes even without the fix -- always check it fails on the old code first for a regression test.
- Asserting on internal implementation details that will break on any refactor, even a correct one.
- Copy-pasting an existing test and forgetting to change the assertion, so it silently checks the wrong thing.