491a45dd43
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4.0 KiB
4.0 KiB
name, description
| name | description |
|---|---|
| test-writer | Write comprehensive tests for new or changed code. Use automatically when new features are added, functions are created, or behavior is modified. |
Write comprehensive tests for the code that was just added or changed.
Step 1: Discover What Changed
- Check
git diffandgit diff --cachedto identify new/modified functions, classes, and modules - Read each changed file to understand the behavior being added
- Identify the project's existing test framework, patterns, and conventions by finding existing test files
- Place new test files next to the source files or in the project's established test directory — match whatever the project already does
Step 2: Analyze Every Code Path
For each new or modified function/method/component, map out:
- Happy path — normal input, expected output
- Edge cases — empty input, single element, boundary values (0, 1, -1, MAX_INT)
- Null/undefined/nil — what happens with missing data
- Type boundaries — wrong types, type coercion traps
- Error paths — invalid input, network failures, timeouts, permission denied
- Concurrency — race conditions, parallel calls with shared state
- State transitions — initial state, intermediate states, final state
- Integration points — how this code interacts with its dependencies
Step 3: Write the Tests
For EACH scenario identified above, write a test. No skipping.
Structure
- One assertion per test — if a test name needs "and", split it into two tests
- Descriptive names — test names read as sentences describing the behavior:
should return empty array when input is emptyshould throw ValidationError when email format is invalidshould retry 3 times before failing on network timeout
- Arrange-Act-Assert — set up, execute, verify. Clear separation.
What to Test
Pure functions / business logic:
- Every branch (if/else, switch, ternary)
- Every thrown error with exact error type and message
- Return value types and shapes
- Side effects (mutations, calls to external services)
API endpoints / handlers:
- Success response (status code, body shape, headers)
- Validation errors for each field (missing, wrong type, out of range)
- Authentication/authorization failures
- Rate limiting behavior if applicable
- Idempotency for non-GET methods
UI components (if applicable):
- Renders without crashing with required props
- Renders correct content for each state (loading, error, empty, populated)
- User interactions trigger correct callbacks (click, submit, type, select)
- Accessibility: focusable, keyboard navigable, correct ARIA attributes
- Conditional rendering — each branch shows/hides correct elements
Database / data layer:
- CRUD operations return correct data
- Unique constraints reject duplicates
- Cascade deletes work as expected
- Transactions roll back on failure
Async operations:
- Successful resolution
- Rejection / error handling
- Timeout behavior
- Cancellation if supported
- Concurrent calls don't interfere
Mocking Rules
- Prefer real implementations over mocks
- Only mock at system boundaries: network, filesystem, clock, random
- Never mock the code under test
- If you mock, verify the mock was called with expected arguments
- Reset mocks between tests — no shared state leaking
Step 4: Verify
- Run the new tests — confirm they all pass
- Temporarily break the code (change a return value or condition) — confirm at least one test fails
- If no test fails when code is broken, the tests are useless — rewrite them
- Check coverage: every new function should have at least one test, every branch should be exercised
Output
- Complete, runnable test file(s) — not snippets
- Tests grouped by the function/component they cover
- A brief summary: how many tests, what scenarios covered, any gaps you couldn't cover and why