atdd
Acceptance Test-Driven Development (Outside-In TDD)
Philosophy
Core principle: We only build what the outside needs. Start at the user-facing boundary — an API endpoint, CLI command, or UI interaction — and let the outer behavior drive every design decision inward.
Two feedback loops run simultaneously: an outer acceptance test that defines "done" for the feature, and inner unit tests that drive each layer's implementation. Mocks aren't just test isolation — they're the mechanism for discovering what the next layer inward needs to do before it exists.
See double-loop.md for the loop mechanics and acceptance-tests.md for what makes a good acceptance test.
Anti-Pattern: Inside-Out Guessing
Don't start by building domain logic or infrastructure hoping it'll compose into the right feature. Building bottom-up means you're guessing what the outer layer will need.
The acceptance test is the anchor. Every design decision flows from it.
Workflow
1. Planning
Before any code:
- Confirm what the user observes when the feature works (the acceptance criterion)
- Identify the system entry point (API route, command handler, event listener)
- Sketch the acceptance test scenario in Given/When/Then form
- Identify the layers you'll traverse (e.g., handler → service → repository)
- Get user approval on the scenario and layer map
Ask: "What does success look like from outside the system?"
2. Walking Skeleton (if new architecture)
If this is a greenfield project or a new architectural slice:
- Write ONE acceptance test through the full stack
- Implement the thinnest path that connects all layers — even if trivially
- Goal: prove the architecture works before building real features
See double-loop.md for details.
3. Double Loop
Outer RED: Write a failing acceptance test for the feature.
Inner loop — repeat for each layer, working outside → in:
RED: Write unit test for current layer object
Mock the next layer's collaborator (this discovers its interface)
GREEN: Implement just enough to pass
Move inward: the mocked collaborator becomes the next object to implement
See interface-discovery.md for how mocking discovers interfaces. See collaboration-tests.md for how to write unit tests at each layer.
Outer GREEN: When all layers are implemented and connected, the acceptance test passes.
4. Refactor
After outer GREEN:
- Extract clean interfaces from the contracts your mocks revealed
- Replace in-memory fakes with real implementations where needed
- Write contract tests to verify real implementations match mock contracts
- Apply standard refactoring (duplication, long methods, etc.)
See refactoring.md for candidates.
Checklist Per Cycle
[ ] Acceptance test describes what the user observes — not internal behavior
[ ] Each unit test mocks only the immediate next-layer collaborator
[ ] Mock expectations are the specification for the collaborator's interface
[ ] No layer exists without a test that drove it
[ ] Acceptance test turns GREEN only when all layers are real (no mocks left in the path)
More from maxmurr/agents-skills
submit-pr
Submit implementation as a pull request. Runs tests, creates a PR with the Linear issue linked, and posts the PR URL as a comment on the Linear issue. Use when implementation is complete and user wants to open a PR, submit work, or create a pull request.
2index-knowledge
Generate hierarchical AGENTS.md + CLAUDE.md knowledge base for a codebase. Creates root + complexity-scored subdirectory documentation with both file types.
2tdd
Test-driven development with red-green-refactor loop. Use when user wants to build features or fix bugs using TDD, mentions "red-green-refactor", wants integration tests, or asks for test-first development.
1prd-to-issues
Break a PRD into independently-grabbable Linear issues using tracer-bullet vertical slices. Use when user wants to convert a PRD to issues, create implementation tickets, or break down a PRD into work items.
1write-a-prd
Create a PRD through user interview, codebase exploration, and module design, then submit as a Linear issue. Use when user wants to write a PRD, create a product requirements document, or plan a new feature.
1start-issue
Kick off implementation of a Linear issue. Fetches the issue and its parent PRD, creates a git branch using Linear's suggested branch name, and presents a consolidated context summary ready for development. Use when starting work on a Linear issue, picking up a ticket, or when user says "start issue TEAM-123", "work on TEAM-123", or "pick up TEAM-123".
1