# Test

> Write or run tests, check coverage, or drive TDD. Triggers "write tests", "run tests", "coverage", "TDD", "red-green-refactor", or a pre-merge test pass.

- Skill: `darkroomengineering/test` (Agent Skill)
- Install (CLI): `npx skillmds@latest add darkroomengineering/test`
- Raw SKILL.md: https://api.skillmd.com/api/skills/darkroomengineering/test/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: darkroomengineering (https://skillmd.com/u/darkroomengineering)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/darkroomengineering/test

---


# Testing Workflow

Delegates to the Tester agent for test coverage and verification.

## Workflow

1. **Identify** - Determine what needs testing (component, hook, utility, integration)
2. **Write** - Create test files colocated with source (e.g., `button.test.tsx`)
3. **Run** - Execute tests and verify results
4. **Report** - Summarize coverage and gaps

## Testing Priorities

1. **Critical paths** - Auth, payments, core features
2. **Edge cases** - Error states, empty states, boundaries
3. **User interactions** - Forms, buttons, navigation
4. **Integration points** - API calls, external services

## Rationalization Counters

If you catch yourself thinking any of the following, STOP — you are skipping testing:

| Rationalization | Why It's Wrong |
|---|---|
| "This is too simple to test" | Simple functions with edge cases are exactly what tests catch |
| "I'll add tests later" | Later never comes; untested code ships and breaks |
| "The types guarantee correctness" | Types check structure, not logic — `add(a, b)` returning `a - b` passes TypeScript |
| "It's just UI, tests don't help" | Interaction tests catch regressions that visual review misses |
| "Manual testing is enough" | Manual testing doesn't run in CI and doesn't prevent regressions |
| "Tests are passing immediately" | Tests that pass on first run without failing first may not be testing what you think — verify the test actually exercises the code path |

## Red Flags

- **Tests pass immediately on first write**: Suspicious. Verify the test would fail if the implementation were wrong.
- **No assertions**: A test without assertions is not a test.
- **Mocking everything**: If you mock the thing you're testing, you're testing the mock.
- **A batch of tests written before any has run**: a batch against *imagined* behavior pins what you guessed — those tests fail on harmless changes and pass while the real path is broken. Write one, watch it go red, earn green, then write the next; each cycle tells you what the next test should actually assert.
- **Asserting internals**: assert observable behavior through the outermost practical entry point (return values, exit codes, persisted rows, rendered output) — never which internal functions ran. A public-surface test survives a rewrite of everything underneath; an internals test breaks on every refactor and pins implementation, not behavior.

## Output

Return a summary:
- **Tests written**: New test files/cases
- **Tests passing**: Status
- **Coverage**: Key areas covered
- **Gaps**: What still needs testing

---

## Variant: TDD (test-first discipline)

A test-first discipline that produces tests which describe **behavior** through public interfaces, not implementation. Such tests survive refactors. Tests coupled to internals do not — they break the moment you rename a function and pass when behavior actually breaks.

Before exploring the codebase, follow [../context-doc/DOMAIN-AWARENESS.md](../context-doc/DOMAIN-AWARENESS.md). Test names and interface vocabulary should match the project's `CONTEXT.md`.

### Anti-pattern: horizontal slices

**Do not write all tests first, then all implementation.** That produces tests describing *imagined* behavior. They test the *shape* of things (data structures, function signatures) instead of user-facing capability. They go insensitive to real changes — they pass when behavior breaks and fail when behavior is fine.

```
WRONG (horizontal):
  RED:   test1, test2, test3, test4, test5
  GREEN: impl1, impl2, impl3, impl4, impl5

RIGHT (vertical):
  RED→GREEN: test1 → impl1
  RED→GREEN: test2 → impl2
  ...
```

Each cycle responds to what you learned from the previous one. You can only write the right test for behavior `N` after implementing behavior `N−1`.

### Workflow

#### 1. Plan

Before writing any code:

- Confirm with the user what interface changes are needed
- Confirm which behaviors to test (prioritize — you can't test everything)
- List the **behaviors** to test (not implementation steps)
- Get user approval on the plan

Ask: *"What should the public interface look like? Which behaviors are most important?"*

#### 2. Tracer bullet

Write **one** test confirming **one** thing about the system:

```
RED:   test for first behavior → fails
GREEN: minimal code to pass → passes
```

This proves the path works end-to-end. Don't move on until it passes.

#### 3. Incremental loop

For each remaining behavior:

```
RED:   next test → fails
GREEN: minimal code to pass → passes
```

To run the red→green cycle autonomously across turns, set
`/goal every planned behavior has a passing test and the full suite exits 0`.
The evaluator reads the test output from the transcript after each turn — don't
phrase the condition as something only the runtime can prove (file flags, etc.).

Rules:

- One test at a time
- Only enough code to pass the current test
- Don't anticipate future tests
- Keep tests focused on observable behavior

#### 4. Refactor

After all tests pass, look for cleanup:

- Extract duplication
- Deepen modules — move complexity behind simple interfaces
- Apply naming from `CONTEXT.md`
- Run the full test suite after each refactor step

**Never refactor while red.** Get to green first.

### Per-cycle checklist

- [ ] Test describes behavior, not implementation
- [ ] Test uses only the public interface
- [ ] Test would survive an internal refactor
- [ ] Code is minimal for this test
- [ ] No speculative features added

### When TDD is the wrong tool

- One-shot scripts, prototypes, throwaway exploration
- UI work where the "behavior" is visual and a snapshot/visual test is more useful
- Code where the public interface is dictated by an external spec (just write the conformance test, then implement)

For these, use `/build` (scaffold-then-test) or `/fix` (existing-bug pipeline) instead.

