Test Seams
Adapted from https://github.com/mattpocock/skills (mattpocock/skills, MIT) — rewritten, not copied.
What a good test is
Verifies behaviour through a public interface, not implementation detail. Reads like a spec: "user can checkout with valid cart" tells you what capability exists and survives a refactor because it does not care about internal structure. Expected values come from an independent source of truth (a known-good literal, a worked example, the spec), never recomputed the way the code computes them.
Confirm seams before writing tests
A seam is the public boundary you test at (see deep-modules). Before writing any test, write down the seams under test and confirm them with the user. No test at an unconfirmed seam. You cannot test everything; agreeing the seams up front is how effort lands on critical paths and complex logic instead of every edge case. Ask: "What is the public interface, and which seams should we test?"
The three anti-patterns
| Name |
Tell |
Fix |
| Implementation-coupled |
Mocks internal collaborators, tests private methods, asserts via a side channel (queries the DB instead of the interface). Breaks on refactor when behaviour has not changed |
Test at the seam, through the interface only |
| Tautological |
Assertion recomputes the expected value the way the code does (expect(add(a,b)).toBe(a+b), a hand-derived snapshot, a constant equal to itself). Passes by construction, can never disagree with the code |
Expected value from an independent source |
| Horizontal slicing |
All tests first, then all implementation. Tests verify imagined behaviour and its shape, go insensitive to real change, lock in test structure before the implementation is understood |
Vertical slices: one test, one minimal implementation, repeat; each test a tracer bullet |
Loop rules
- Red before green. Failing test first, then only enough code to pass it. No speculative features.
- One slice at a time. One seam, one test, one minimal implementation per cycle.
- Refactoring is not in the loop. It belongs to review (
code-review, cavecrew-reviewer), after green.
1---2name: test-seams3description: The reference that makes a red-green loop produce tests worth keeping, what a good test is, confirming the seams under test before writing any, and the three anti-patterns that make tests break on refactors or pass by construction. Use when writing or reviewing tests, doing red-green-refactor, or deciding what to test. Complements the loop itself (superpowers:test-driven-development drives red-green); this is the quality gate on what it produces.4---56# Test Seams78Adapted from https://github.com/mattpocock/skills (mattpocock/skills, MIT) — rewritten, not copied.910## What a good test is11Verifies behaviour through a public interface, not implementation detail. Reads like a spec: "user can checkout with valid cart" tells you what capability exists and survives a refactor because it does not care about internal structure. Expected values come from an independent source of truth (a known-good literal, a worked example, the spec), never recomputed the way the code computes them.1213## Confirm seams before writing tests14A **seam** is the public boundary you test at (see `deep-modules`). Before writing any test, write down the seams under test and confirm them with the user. No test at an unconfirmed seam. You cannot test everything; agreeing the seams up front is how effort lands on critical paths and complex logic instead of every edge case. Ask: "What is the public interface, and which seams should we test?"1516## The three anti-patterns17| Name | Tell | Fix |18|---|---|---|19| Implementation-coupled | Mocks internal collaborators, tests private methods, asserts via a side channel (queries the DB instead of the interface). Breaks on refactor when behaviour has not changed | Test at the seam, through the interface only |20| Tautological | Assertion recomputes the expected value the way the code does (`expect(add(a,b)).toBe(a+b)`, a hand-derived snapshot, a constant equal to itself). Passes by construction, can never disagree with the code | Expected value from an independent source |21| Horizontal slicing | All tests first, then all implementation. Tests verify imagined behaviour and its shape, go insensitive to real change, lock in test structure before the implementation is understood | Vertical slices: one test, one minimal implementation, repeat; each test a tracer bullet |2223## Loop rules24- **Red before green.** Failing test first, then only enough code to pass it. No speculative features.25- **One slice at a time.** One seam, one test, one minimal implementation per cycle.26- **Refactoring is not in the loop.** It belongs to review (`code-review`, `cavecrew-reviewer`), after green.