Skip to content
Testing
Skill

/atdd

Use to drive feature work through the Acceptance Test Driven Development workflow — Given/When/Then specs before code, a project-specific test pipeline, and two parallel test streams (acceptance + unit). Triggers — "/atdd", "build a feature", "implement a feature", "add

From plugin
atdd
14922 skills2 agents4 commands2 hooks
Install
$ npx -y skills add swingerman/disciplined-agentic-engineering --skill atdd --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/atdd

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use to drive feature work through the Acceptance Test Driven Development workflow — Given/When/Then specs before code, a project-specific test pipeline, and two parallel test streams (acceptance + unit). Triggers — "/atdd", "build a feature", "implement a feature", "add

SKILL.md

atdd.SKILL.md
name: atdd
description: >-
  Use to drive feature work through the Acceptance Test Driven Development
  workflow — Given/When/Then specs before code, a project-specific test
  pipeline, and two parallel test streams (acceptance + unit). Triggers —
  "/atdd", "build a feature", "implement a feature", "add functionality",
  "start development", "write acceptance tests", "write specs", "use ATDD",
  "use TDD with acceptance tests".

Acceptance Test Driven Development

Enforce the ATDD workflow for feature development. This methodology is adapted from Robert C. Martin's acceptance test approach.

Core Principle

> "The two different streams of tests cause Claude to think much more > deeply about the structure of the code." > — Robert C. Martin

Two test streams constrain development:

  • **Acceptance tests** define WHAT the system does (external observables)
  • **Unit tests** define HOW the system does it (internal structure)

Both must pass. Neither alone is sufficient.

Workflow

Follow these steps strictly, in order. Do not skip steps.

Before Step 1, create one TodoWrite todo per step of this workflow (Steps 1–7), all at once — the full list up front, as a roadmap. Flip each todo to `in_progress` / `completed` as you go. See `${CLAUDE_PLUGIN_ROOT}/references/progress-indicator.md`.

Step 1: Understand the Feature

Before writing anything, understand what is being built:

  • Ask clarifying questions about the feature's purpose
  • Identify the domain language (what terms do users/stakeholders use?)
  • Determine success criteria: what observable behavior proves it works?
  • Scope it: "just enough specs for this sprint" — do not design the whole system

Step 2: Write GWT Acceptance Specs

Write the feature's `spec.md` in **standard Gherkin** (DAE Foundation §7):

Feature: <feature name>

Scenario: <behavior being specified>
  Given <precondition in domain language>
  And <another precondition if needed>
  When <the action the user/system takes>
  Then <observable outcome>
  And <another observable outcome if needed>

Scenario Outline: <a behavior with varying data>
  Given <a step with a <parameter>>
  ...

  Examples:
    | parameter | expected |
    | value     | result   |

`spec.md` is markdown — prose and headings around the Gherkin are fine; the parser ignores non-Gherkin lines.

> **Migrating from the legacy `;=== .txt` format?** Run the converter: > `dae_gherkin_convert.py specs/feature.txt features/NNN-slug/spec.md`. > The `.txt` format is deprecated; new specs are Gherkin `spec.md`.

**Format rules:**

  • `Scenario:` names one behavior; `Scenario Outline:` + `Examples:` for varying data
  • `Given` sets preconditions; `When` the action (one per scenario, ideally); `Then` the observable outcome
  • `And` continues the previous keyword
  • Use natural domain language, never implementation language

**The spec-leakage rule — CRITICAL:**

Specs must describe **external observables only**. Never reference:

  • Class names, function names, method names
  • Database tables, columns, queries
  • API endpoints, HTTP methods, status codes
  • Framework-specific terms (controllers, services, repositories)
  • Internal state, variables, data structures
  • File paths or module names
BAD:  Given the UserService has an empty userRepository
GOOD: Given there are no registered users

BAD:  When a POST request is sent to /api/users
GOOD: When a new user registers with email "bob@example.com"

BAD:  Then the database contains 1 row in the users table
GOOD: Then there is 1 registered user

**Present specs to the user for approval before proceeding.** Specs are co-authored, but the human has final approval — ferociously defended.

Step 3: Generate the Test Pipeline

The pipeline's front end is portable and shipped — you don't generate it:

1. **Parser** — `dae_gherkin.py` parses `spec.md` → `.build/spec.json`, the fixed JSON IR (see the engineer plugin's `references/spec-ir.md`).

Invoke the `pipeline-builder` agent to generate the **project-specific** half:

2. **Generator** — reads `.build/spec.json`, produces executable test files for the project's framework (pytest, Jest, JUnit, Go testing, RSpec, etc.) 3. **Step handlers** — bind each step's exact text to system internals.

The generator must have **deep knowledge of the system internals**. This is NOT Cucumber — it produces complete, runnable tests that call into the system, not stubs requiring manual fixtures.

`pipeline-builder` also generates a runner so the user can run:

# parse spec.md → IR → generate tests → run tests
./run-acceptance-tests.sh

Step 4: Run Acceptance Tests (Red)

Run the generated acceptance tests. They should **fail** — this confirms the specs describe behavior that doesn't exist yet.

If they pass, either:

  • The behavior already exists (specs are redundant — revise or remove)
  • The generator is not testing the right thing (fix the pipeline)

Step 5: Implement with TDD

Now implement the feature using standard TDD:

1. Write a failing unit test for the smallest piece of the feature 2. Write minimal code to make it pass 3. Refactor 4. Repeat until the acceptance tests pass

**Faster iteration with impact analysis:** if the project has `acceptance.impact_analysis: on`, the runner's impact-run mode (`dae_impact.py select`) runs only the scenarios your change affects — use it for the tight TDD loop. The **full** acceptance run still gates Step 5's completion: do not mark the feature done until every scenario passes a full run.

**Both streams must pass:**

  • Unit tests verify internal correctness
  • Acceptance tests verify external behavior matches specs

Step 6: Review Specs for Leakage

After implementation, invoke the `spec-guardian` agent to review all spec files for implementation details that may have crept in during development.

If leakage is found, clean the specs back to domain language.

Step 7: Iterate

Return to Step 1 for the next feature. Each iteration adds

Read more
Ships withatdd

A methodology kit for engineering-led AI development — spec-driven, test-driven, charter-bound. ATDD + mutation testing + deterministic guardrails. AI agents do the typing. Engineers stay in charge of architecture, behavior contracts, and verification.

Get the whole plugin

Other skills on atdd.

clarify
Skill

clarify

Use when a single DAE artifact has ambiguities to resolve. Triggers — "/engineer.clarify", "clarify this spec", "resolve ambiguities", "this is vague — tighten…

@swingerman@swingermanView Skill