docs(adr): ADR-011 TDD foundation; update AGENTS.md per-feature
Captures the decision to add @repo/core-testing, factories, contract suites, vitest safety defaults, coverage thresholds, Storybook test-runner, and CI as one cohesive TDD foundation. Per-feature AGENTS.md gains a Tests section pointing to factories, contract suite, and the canonical test commands. Spec: §7.4, §7.5 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
70
docs/decisions/adr-011-tdd-foundation.md
Normal file
70
docs/decisions/adr-011-tdd-foundation.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# ADR-011: TDD Foundation
|
||||
|
||||
**Status:** Accepted
|
||||
**Date:** 2026-05-05
|
||||
**Supersedes:** none
|
||||
**Spec:** docs/superpowers/specs/2026-05-05-tdd-foundation-design.md
|
||||
|
||||
## Context
|
||||
|
||||
The vertical-feature monorepo refactor (ADRs 001-010) established
|
||||
clean architecture with per-feature DI containers but did not enforce
|
||||
TDD as the path of least resistance. Agentic workers were producing
|
||||
code-first commits with tests added later, leading to test theatre and
|
||||
mock/real drift.
|
||||
|
||||
## Decision
|
||||
|
||||
1. **New package `@repo/core-testing` (tag: tooling)** — shared test
|
||||
utilities: defineFactory, defineContractSuite, renderWithProviders,
|
||||
mock-payload helpers, jsdom setup file. Tagged `tooling` so any
|
||||
package may depend on it as devDependency without boundary violation.
|
||||
|
||||
2. **Vitest base configs split into node + jsdom** with safety defaults
|
||||
(clearMocks, restoreMocks, mockReset, unstubGlobals, sequence.shuffle)
|
||||
and coverage thresholds (80/75/80/80 baseline; 100% in entities +
|
||||
use-cases + controllers).
|
||||
|
||||
3. **Factories per feature** in `src/__factories__/` replace inline
|
||||
fixtures. Stable date defaults (2026-01-01) so snapshot diffs reflect
|
||||
SUT behavior only.
|
||||
|
||||
4. **Contract suites per repository interface** in `src/__contracts__/`
|
||||
run against every implementation (Mock + Payload). Eliminates the
|
||||
class of bug where the mock and the real impl drift apart.
|
||||
|
||||
5. **Tests in core-* packages and apps** — composition smoke tests
|
||||
(appRouter, payloadConfig, bind-production, providers).
|
||||
|
||||
6. **Storybook test-runner** — every story executed as a smoke test.
|
||||
|
||||
7. **CI workflow** — typecheck + lint + boundaries + test + build +
|
||||
e2e + storybook on every PR. Coverage uploaded as artifact.
|
||||
|
||||
8. **Two new docs** — tdd-workflow.md (process) + restructured
|
||||
adding-a-feature.md (interleaves tests with impl).
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
- **Fixture files instead of factories** — rejected. Fixtures rot with
|
||||
schema changes and require manual updates per test.
|
||||
- **One shared test file per impl** — rejected. Contract suites give
|
||||
the same coverage in fewer LOC and prevent drift.
|
||||
- **Real Postgres in tests via testcontainers** — rejected for unit
|
||||
tests (slow, complex). Repository contract suites + vi.mock('payload')
|
||||
give equivalent confidence in milliseconds.
|
||||
- **Stryker mutation testing** — deferred. Coverage thresholds + contract
|
||||
suites get us most of the way; mutation testing is incremental.
|
||||
|
||||
## Consequences
|
||||
|
||||
- New package to maintain (small, mostly stable surface).
|
||||
- Coverage thresholds may fail builds initially; we add tests to cross
|
||||
threshold as part of Plan 7.
|
||||
- Sequence shuffle may surface latent flakes; we fix as found.
|
||||
- Templates for new features now require writing tests first; this is
|
||||
by design.
|
||||
|
||||
## Refines
|
||||
|
||||
- ADR-006 (boundary tags) — adds @repo/core-testing as a tooling package.
|
||||
Reference in New Issue
Block a user