# Writing Tests

> Writes focused unit and integration tests for fn(args, deps) code with explicit deps mocks and clear arrange-act-assert. Use this skill when authoring or refactoring test files for TypeScript functions and modules. Do not use when/for TDD process discipline alone (use tdd-workflow) or load testing (use performance-testing).

- Skill: `jagreehal/writing-tests` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add jagreehal/writing-tests`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jagreehal/writing-tests/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: jagreehal (https://skillmd.com/u/jagreehal)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/jagreehal/writing-tests

---


# Writing Tests

## Critical rules

- **Names describe outcomes, not actions:** `[outcome] when [condition]` — e.g. `returns empty array when input is null`, not `test null input`.
- **Assertions match the title.** If the name claims "different IDs", assert the IDs differ — not just length.
- **Assert specific values**, not `toBeDefined()` / `toBeTruthy()`. Specific assertions catch specific bugs.
- **One concept per test.** If you need "and" in the name, split.
- **Bugs cluster.** One bug → test related inputs, same pattern elsewhere, same assumption, same type.
- Assert **behavior** (Results, returned values), not implementation (`toHaveBeenCalledWith` for SQL shape).
- No `vi.mock()` for app logic — `mock<DepsType>()` from vitest-mock-extended.
- Before WRONG/CORRECT examples or edge-case checklists, read the matching resource below.

## Workflow

1. Name the test as a specification: reading names alone should describe the function.
2. Structure Arrange → Act → Assert. Keep one reason to fail.
3. For `Result<T, E>`: assert `result.ok` and the exact `error` or `value`.
4. Cover relevant edge cases (numbers, strings, collections, dates, null/undefined, domain constraints). Before expanding coverage, read [references/edge-cases.md](references/edge-cases.md).
5. On a bug fix: add the failing case, then neighbors (null→undefined→empty; same boundary elsewhere).
6. Prefer observable outcomes over internal call assertions so refactors don't break tests.

Adapted from [BugMagnet](https://github.com/gojko/bugmagnet-ai-assistant) (Gojko Adzic), aligned with `fn(args, deps)` and Result patterns.

## Resources

- [references/examples.md](references/examples.md) — naming, assertions, Result tests, AAA, complete getUser suite. Read when drafting or reviewing a test.
- [references/edge-cases.md](references/edge-cases.md) — type and domain checklists. Read when expanding coverage.
- [references/rationalizations.md](references/rationalizations.md) — excuse→reality and red flags. Read when tempted to weaken a test.

## Validation

- [ ] Names use `[outcome] when [condition]`
- [ ] Each assertion verifies the title's claim with specific values
- [ ] One concept per test (no "and" in the name)
- [ ] Result tests assert `ok` and exact error/value
- [ ] Relevant edge cases covered; bug fixes spawned cluster tests
- [ ] Behavior asserted, not brittle internal calls; deps via `mock<DepsType>()`

## Constraints

- Layer choice (unit vs integration vs e2e) is `testing-strategy`, not this skill.
- Red-green-refactor discipline is `tdd-workflow` (this skill is RED-phase craft).
- Adjacent: `result-types`, `validation-boundary`, `fn-args-deps`, `design-principles` (hard-to-test often means design smell).

