SuperAPI AI Directory

tdd

Testing & quality

View repository

Updated 10-16 09:19

About this skill

Test-Driven Development

TDD is a red -> green loop. This skill is the reference that makes that loop produce tests worth keeping: what a good test is, where tests should live, anti-patterns, and the rules of the loop. Consult these before and during each cycle, not after the fact.

When exploring the codebase, read GLOSSARY.md(if it exists) to align test names and interface vocabulary with the project's domain language, and respect the ADRs for the areas you touch.

What a good test is

Tests should verify behavior through public interfaces, not implementation details. The code can change completely; the tests should not change along with it. A good test reads like a specification: "user can checkout with valid cart" clearly states what capability exists; because it does not care about internal structure, it can withstand refactors.

For examples see tests.md, for mocking rules see mocking.md。

Seams: where tests go

Seam is the public boundary you test: an interface where you can observe behavior but do not reach inside. Tests go on seams, never against internals.

Only test pre-approved seams. Before writing any test, write down the seams to be tested and confirm them with the user. Do not write tests for unconfirmed seams. You cannot test everything; approving seams up front lets you focus testing effort on critical paths and complex logic, rather than every edge case.

Ask: "What's the public interface, and which seams should we test?"

When the shape of the interface is itself the problem (how deep a module should be, where a seam should go, what an interface should expose), call the Skill tool and specify codebase-design to get the vocabulary. It is the shared source for the terms module, interface, depth, seam, adapter, leverage, and locality, a reference to consult rather than a session to run.

Anti-patterns

  • Implementation-coupled: mocking internal collaborators, testing private methods, or verifying through a side channel (for example, querying the database directly instead of going through the interface). The tell is that the test fails on a refactor while behavior has not changed.
  • Tautological: an assertion recomputes the expected value in the same way as the code (expect(add(a, b)).toBe(a + b), manually generating a snapshot using the same logic, asserting a constant equals itself), so it passes by construction and can never disagree with the code. Expected values must come from an independent source of truth: a known-good literal, a worked example, or a spec.
  • Horizontal slicing: writing all tests first, then all the implementation. Batch tests verify imagined behavior: you test the thing's shape, not user-facing behavior; tests become insensitive to real changes and commit to a test structure before the implementation is understood. Use instead vertical slices: one test -> one implementation -> repeat, with each test responding to what the previous round tracer bullet。

Rules of the loop

  • Red before green. Write the failing test first, then write only enough code to make it pass. Do not anticipate future tests, and do not add speculative features.
  • One slice at a time. Each cycle handles only one seam, one test, one minimal implementation.
  • Refactoring is not part of the loop. Refactoring belongs to the review stage (see code-review skill), does not belong to the red -> green implementation cycle.