23 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	ATDD (Acceptance Test-Driven Development) Workflow
Generates failing acceptance tests BEFORE implementation following TDD's red-green-refactor cycle. Creates comprehensive test coverage at appropriate levels (E2E, API, Component) with supporting infrastructure (fixtures, factories, mocks) and provides an implementation checklist to guide development toward passing tests.
Core Principle: Tests fail first (red phase), guide development to green, then enable confident refactoring.
Usage
bmad tea *atdd
The TEA agent runs this workflow when:
- User story is approved with clear acceptance criteria
 - Development is about to begin (before any implementation code)
 - Team is practicing Test-Driven Development (TDD)
 - Need to establish test-first contract with DEV team
 
Inputs
Required Context Files:
- Story markdown (
{story_file}): User story with acceptance criteria, functional requirements, and technical constraints - Framework configuration: Test framework config (playwright.config.ts or cypress.config.ts) from framework workflow
 
Workflow Variables:
story_file: Path to story markdown with acceptance criteria (required)test_dir: Directory for test files (default:{project-root}/tests)test_framework: Detected from framework workflow (playwright or cypress)test_levels: Which test levels to generate (default: "e2e,api,component")primary_level: Primary test level for acceptance criteria (default: "e2e")start_failing: Tests must fail initially - red phase (default: true)use_given_when_then: BDD-style test structure (default: true)network_first: Route interception before navigation to prevent race conditions (default: true)one_assertion_per_test: Atomic test design (default: true)generate_factories: Create data factory stubs using faker (default: true)generate_fixtures: Create fixture architecture with auto-cleanup (default: true)auto_cleanup: Fixtures clean up their data automatically (default: true)include_data_testids: List required data-testid attributes for DEV (default: true)include_mock_requirements: Document mock/stub needs (default: true)auto_load_knowledge: Load fixture-architecture, data-factories, component-tdd fragments (default: true)share_with_dev: Provide implementation checklist to DEV agent (default: true)output_checklist: Path for implementation checklist (default:{output_folder}/atdd-checklist-{story_id}.md)
Optional Context:
- Test design document: For risk/priority context alignment (P0-P3 scenarios)
 - Existing fixtures/helpers: For consistency with established patterns
 - Architecture documents: For understanding system boundaries and integration points
 
Outputs
Primary Deliverable:
- ATDD Checklist (
atdd-checklist-{story_id}.md): Implementation guide containing:- Story summary and acceptance criteria breakdown
 - Test files created with paths and line counts
 - Data factories created with patterns
 - Fixtures created with auto-cleanup logic
 - Mock requirements for external services
 - Required data-testid attributes list
 - Implementation checklist mapping tests to code tasks
 - Red-green-refactor workflow guidance
 - Execution commands for running tests
 
 
Test Files Created:
- E2E tests (
tests/e2e/{feature-name}.spec.ts): Full user journey tests for critical paths - API tests (
tests/api/{feature-name}.api.spec.ts): Business logic and service contract tests - Component tests (
tests/component/{ComponentName}.test.tsx): UI component behavior tests 
Supporting Infrastructure:
- Data factories (
tests/support/factories/{entity}.factory.ts): Factory functions using @faker-js/faker for generating test data with overrides support - Test fixtures (
tests/support/fixtures/{feature}.fixture.ts): Playwright fixtures with setup/teardown and auto-cleanup - Mock/stub documentation: Requirements for external service mocking (payment gateways, email services, etc.)
 - data-testid requirements: List of required test IDs for stable selectors in UI implementation
 
Validation Safeguards:
- All tests must fail initially (red phase verified by local test run)
 - Failure messages are clear and actionable
 - Tests use Given-When-Then format for readability
 - Network-first pattern applied (route interception before navigation)
 - One assertion per test (atomic test design)
 - No hard waits or sleeps (explicit waits only)
 
Key Features
Red-Green-Refactor Cycle
RED Phase (TEA Agent responsibility):
- Write failing tests first defining expected behavior
 - Tests fail for right reason (missing implementation, not test bugs)
 - All supporting infrastructure (factories, fixtures, mocks) created
 
GREEN Phase (DEV Agent responsibility):
- Implement minimal code to pass one test at a time
 - Use implementation checklist as guide
 - Run tests frequently to verify progress
 
REFACTOR Phase (DEV Agent responsibility):
- Improve code quality with confidence (tests provide safety net)
 - Extract duplications, optimize performance
 - Ensure tests still pass after changes
 
Test Level Selection Framework
E2E (End-to-End):
- Critical user journeys (login, checkout, core workflows)
 - Multi-system integration
 - User-facing acceptance criteria
 - Characteristics: High confidence, slow execution, brittle
 
API (Integration):
- Business logic validation
 - Service contracts and data transformations
 - Backend integration without UI
 - Characteristics: Fast feedback, good balance, stable
 
Component:
- UI component behavior (buttons, forms, modals)
 - Interaction testing (click, hover, keyboard navigation)
 - Visual regression and state management
 - Characteristics: Fast, isolated, granular
 
Unit:
- Pure business logic and algorithms
 - Edge cases and error handling
 - Minimal dependencies
 - Characteristics: Fastest, most granular
 
Selection Strategy: Avoid duplicate coverage. Use E2E for critical happy path, API for business logic variations, component for UI edge cases, unit for pure logic.
Recording Mode (NEW - Phase 2.5)
atdd can record complex UI interactions instead of AI generation.
Activation: Automatic for complex UI when config.tea_use_mcp_enhancements is true and MCP available
- Fallback: AI generation (silent, automatic)
 
When to Use Recording Mode:
- ✅ Complex UI interactions (drag-drop, multi-step forms, wizards)
 - ✅ Visual workflows (modals, dialogs, animations)
 - ✅ Unclear requirements (exploratory, discovering expected behavior)
 - ✅ Multi-page flows (checkout, registration, onboarding)
 - ❌ NOT for simple CRUD (AI generation faster)
 - ❌ NOT for API-only tests (no UI to record)
 
When to Use AI Generation (Default):
- ✅ Clear acceptance criteria available
 - ✅ Standard patterns (login, CRUD, navigation)
 - ✅ Need many tests quickly
 - ✅ API/backend tests (no UI interaction)
 
How Test Generation Works (Default - AI-Based):
TEA generates tests using AI by:
- Analyzing acceptance criteria from story markdown
 - Inferring selectors from requirement descriptions (e.g., "login button" → 
[data-testid="login-button"]) - Synthesizing test code based on knowledge base patterns
 - Estimating interactions using common UI patterns (click, type, verify)
 - Applying best practices from knowledge fragments (Given-When-Then, network-first, fixtures)
 
This works well for:
- ✅ Clear requirements with known UI patterns
 - ✅ Standard workflows (login, CRUD, navigation)
 - ✅ When selectors follow conventions (data-testid attributes)
 
What MCP Adds (Interactive Verification & Enhancement):
When Playwright MCP is available, TEA additionally:
- 
Verifies generated tests by:
- Launching real browser with 
generator_setup_page - Executing generated test steps with 
browser_*tools (navigate,click,type) - Seeing actual UI with 
browser_snapshot(visual verification) - Discovering real selectors with 
browser_generate_locator(auto-generate from live DOM) 
 - Launching real browser with 
 - 
Enhances AI-generated tests by:
- Validating selectors exist in actual DOM (not just guesses)
 - Verifying behavior with 
browser_verify_text,browser_verify_visible,browser_verify_url - Capturing actual interaction log with 
generator_read_log - Refining test code with real observed behavior
 
 - 
Catches issues early by:
- Finding missing selectors before DEV implements (requirements clarification)
 - Discovering edge cases not in requirements (loading states, error messages)
 - Validating assumptions about UI structure and behavior
 
 
Key Benefits of MCP Enhancement:
- ✅ AI generates tests (fast, based on requirements) + MCP verifies tests (accurate, based on reality)
 - ✅ Accurate selectors: Validated against actual DOM, not just inferred
 - ✅ Visual validation: TEA sees what user sees (modals, animations, state changes)
 - ✅ Complex flows: Records multi-step interactions precisely
 - ✅ Edge case discovery: Observes actual app behavior beyond requirements
 - ✅ Selector resilience: MCP generates robust locators from live page (role-based, text-based, fallback chains)
 
Example Enhancement Flow:
1. AI generates test based on acceptance criteria
   → await page.click('[data-testid="submit-button"]')
2. MCP verifies selector exists (browser_generate_locator)
   → Found: button[type="submit"].btn-primary
   → No data-testid attribute exists!
3. TEA refines test with actual selector
   → await page.locator('button[type="submit"]').click()
   → Documents requirement: "Add data-testid='submit-button' to button"
Recording Workflow (MCP-Based):
1. Set generation_mode: "recording"
2. Use generator_setup_page to init recording session
3. For each acceptance criterion:
   a. Execute scenario with browser_* tools:
      - browser_navigate, browser_click, browser_type
      - browser_select, browser_check
   b. Add verifications with browser_verify_* tools:
      - browser_verify_text, browser_verify_visible
      - browser_verify_url
   c. Capture log with generator_read_log
   d. Generate test with generator_write_test
4. Enhance generated tests with knowledge base patterns:
   - Add Given-When-Then comments
   - Replace selectors with data-testid
   - Add network-first interception
   - Add fixtures/factories
5. Verify tests fail (RED phase)
Example: Recording a Checkout Flow
Recording session for: "User completes checkout with credit card"
Actions recorded:
1. browser_navigate('/cart')
2. browser_click('[data-testid="checkout-button"]')
3. browser_type('[data-testid="card-number"]', '4242424242424242')
4. browser_type('[data-testid="expiry"]', '12/25')
5. browser_type('[data-testid="cvv"]', '123')
6. browser_click('[data-testid="place-order"]')
7. browser_verify_text('Order confirmed')
8. browser_verify_url('/confirmation')
Generated test (enhanced):
- Given-When-Then structure added
- data-testid selectors used
- Network-first payment API mock added
- Card factory created for test data
- Test verified to FAIL (checkout not implemented)
Graceful Degradation:
- Recording mode is OPTIONAL (default: AI generation)
 - Requires Playwright MCP (falls back to AI if unavailable)
 - Generated tests enhanced with knowledge base patterns
 - Same quality output regardless of generation method
 
Given-When-Then Structure
All tests follow BDD format for clarity:
test('should display error for invalid credentials', async ({ page }) => {
  // GIVEN: User is on login page
  await page.goto('/login');
  // WHEN: User submits invalid credentials
  await page.fill('[data-testid="email-input"]', 'invalid@example.com');
  await page.fill('[data-testid="password-input"]', 'wrongpassword');
  await page.click('[data-testid="login-button"]');
  // THEN: Error message is displayed
  await expect(page.locator('[data-testid="error-message"]')).toHaveText('Invalid email or password');
});
Network-First Testing Pattern
Critical pattern to prevent race conditions:
// ✅ CORRECT: Intercept BEFORE navigation
await page.route('**/api/data', handler);
await page.goto('/page');
// ❌ WRONG: Navigate then intercept (race condition)
await page.goto('/page');
await page.route('**/api/data', handler); // Too late!
Always set up route interception before navigating to pages that make network requests.
Data Factory Architecture
Use faker for all test data generation:
// tests/support/factories/user.factory.ts
import { faker } from '@faker-js/faker';
export const createUser = (overrides = {}) => ({
  id: faker.number.int(),
  email: faker.internet.email(),
  name: faker.person.fullName(),
  createdAt: faker.date.recent().toISOString(),
  ...overrides,
});
export const createUsers = (count: number) => Array.from({ length: count }, () => createUser());
Factory principles:
- Use faker for random data (no hardcoded values to prevent collisions)
 - Support overrides for specific test scenarios
 - Generate complete valid objects matching API contracts
 - Include helper functions for bulk creation
 
Fixture Architecture with Auto-Cleanup
Playwright fixtures with automatic data cleanup:
// tests/support/fixtures/auth.fixture.ts
import { test as base } from '@playwright/test';
export const test = base.extend({
  authenticatedUser: async ({ page }, use) => {
    // Setup: Create and authenticate user
    const user = await createUser();
    await page.goto('/login');
    await page.fill('[data-testid="email"]', user.email);
    await page.fill('[data-testid="password"]', 'password123');
    await page.click('[data-testid="login-button"]');
    await page.waitForURL('/dashboard');
    // Provide to test
    await use(user);
    // Cleanup: Delete user (automatic)
    await deleteUser(user.id);
  },
});
Fixture principles:
- Auto-cleanup (always delete created data in teardown)
 - Composable (fixtures can use other fixtures via mergeTests)
 - Isolated (each test gets fresh data)
 - Type-safe with TypeScript
 
One Assertion Per Test (Atomic Design)
Each test should verify exactly one behavior:
// ✅ CORRECT: One assertion
test('should display user name', async ({ page }) => {
  await expect(page.locator('[data-testid="user-name"]')).toHaveText('John');
});
// ❌ WRONG: Multiple assertions (not atomic)
test('should display user info', async ({ page }) => {
  await expect(page.locator('[data-testid="user-name"]')).toHaveText('John');
  await expect(page.locator('[data-testid="user-email"]')).toHaveText('john@example.com');
});
Why? If second assertion fails, you don't know if first is still valid. Split into separate tests for clear failure diagnosis.
Implementation Checklist for DEV
Maps each failing test to concrete implementation tasks:
## Implementation Checklist
### Test: User Login with Valid Credentials
- [ ] Create `/login` route
- [ ] Implement login form component
- [ ] Add email/password validation
- [ ] Integrate authentication API
- [ ] Add `data-testid` attributes: `email-input`, `password-input`, `login-button`
- [ ] Implement error handling
- [ ] Run test: `npm run test:e2e -- login.spec.ts`
- [ ] ✅ Test passes (green phase)
Provides clear path from red to green for each test.
Integration with Other Workflows
Before this workflow:
- framework workflow: Must run first to establish test framework architecture (Playwright or Cypress config, directory structure, base fixtures)
 - test-design workflow: Optional but recommended for P0-P3 priority alignment and risk assessment context
 
After this workflow:
- DEV agent implements features guided by failing tests and implementation checklist
 - test-review workflow: Review generated test quality before sharing with DEV team
 - automate workflow: After story completion, expand regression suite with additional edge case coverage
 
Coordinates with:
- Story approval process: ATDD runs after story is approved but before DEV begins implementation
 - Quality gates: Failing tests serve as acceptance criteria for story completion (all tests must pass)
 
Important Notes
ATDD is Test-First, Not Test-After
Critical timing: Tests must be written BEFORE any implementation code. This ensures:
- Tests define the contract (what needs to be built)
 - Implementation is guided by tests (no over-engineering)
 - Tests verify behavior, not implementation details
 - Confidence in refactoring (tests catch regressions)
 
All Tests Must Fail Initially
Red phase verification is mandatory:
- Run tests locally after creation to confirm RED phase
 - Failure should be due to missing implementation, not test bugs
 - Failure messages should be clear and actionable
 - Document expected failure messages in ATDD checklist
 
If a test passes before implementation, it's not testing the right thing.
Use data-testid for Stable Selectors
Why data-testid?
- CSS classes change frequently (styling refactors)
 - IDs may not be unique or stable
 - Text content changes with localization
 - data-testid is explicit contract between tests and UI
 
// ✅ CORRECT: Stable selector
await page.click('[data-testid="login-button"]');
// ❌ FRAGILE: Class-based selector
await page.click('.btn.btn-primary.login-btn');
ATDD checklist includes complete list of required data-testid attributes for DEV team.
No Hard Waits or Sleeps
Use explicit waits only:
// ✅ CORRECT: Explicit wait for condition
await page.waitForSelector('[data-testid="user-name"]');
await expect(page.locator('[data-testid="user-name"]')).toBeVisible();
// ❌ WRONG: Hard wait (flaky, slow)
await page.waitForTimeout(2000);
Playwright's auto-waiting is preferred (expect() automatically waits up to timeout).
Component Tests for Complex UI Only
When to use component tests:
- Complex UI interactions (drag-drop, keyboard navigation)
 - Form validation logic
 - State management within component
 - Visual edge cases
 
When NOT to use:
- Simple rendering (snapshot tests are sufficient)
 - Integration with backend (use E2E or API tests)
 - Full user journeys (use E2E tests)
 
Component tests are valuable but should complement, not replace, E2E and API tests.
Auto-Cleanup is Non-Negotiable
Every test must clean up its data:
- Use fixtures with automatic teardown
 - Never leave test data in database/storage
 - Each test should be isolated (no shared state)
 
Cleanup patterns:
- Fixtures: Cleanup in teardown function
 - Factories: Provide deletion helpers
 - Tests: Use 
test.afterEach()for manual cleanup if needed 
Without auto-cleanup, tests become flaky and depend on execution order.
Knowledge Base References
This workflow automatically consults:
- fixture-architecture.md - Test fixture patterns with setup/teardown and auto-cleanup using Playwright's test.extend()
 - data-factories.md - Factory patterns using @faker-js/faker for random test data generation with overrides support
 - component-tdd.md - Component test strategies using Playwright Component Testing (@playwright/experimental-ct-react)
 - network-first.md - Route interception patterns (intercept before navigation to prevent race conditions)
 - test-quality.md - Test design principles (Given-When-Then, one assertion per test, determinism, isolation)
 - test-levels-framework.md - Test level selection framework (E2E vs API vs Component vs Unit)
 
See tea-index.csv for complete knowledge fragment mapping and additional references.
Example Output
After running this workflow, the ATDD checklist will contain:
# ATDD Checklist - Epic 3, Story 5: User Authentication
## Story Summary
As a user, I want to log in with email and password so that I can access my personalized dashboard.
## Acceptance Criteria
1. User can log in with valid credentials
2. User sees error message with invalid credentials
3. User is redirected to dashboard after successful login
## Failing Tests Created (RED Phase)
### E2E Tests (3 tests)
- `tests/e2e/user-authentication.spec.ts` (87 lines)
  - ✅ should log in with valid credentials (RED - missing /login route)
  - ✅ should display error for invalid credentials (RED - error message not implemented)
  - ✅ should redirect to dashboard after login (RED - redirect logic missing)
### API Tests (2 tests)
- `tests/api/auth.api.spec.ts` (54 lines)
  - ✅ POST /api/auth/login - should return token for valid credentials (RED - endpoint not implemented)
  - ✅ POST /api/auth/login - should return 401 for invalid credentials (RED - validation missing)
## Data Factories Created
- `tests/support/factories/user.factory.ts` - createUser(), createUsers(count)
## Fixtures Created
- `tests/support/fixtures/auth.fixture.ts` - authenticatedUser fixture with auto-cleanup
## Required data-testid Attributes
### Login Page
- `email-input` - Email input field
- `password-input` - Password input field
- `login-button` - Submit button
- `error-message` - Error message container
### Dashboard Page
- `user-name` - User name display
- `logout-button` - Logout button
## Implementation Checklist
### Test: User Login with Valid Credentials
- [ ] Create `/login` route
- [ ] Implement login form component
- [ ] Add email/password validation
- [ ] Integrate authentication API
- [ ] Add data-testid attributes: `email-input`, `password-input`, `login-button`
- [ ] Run test: `npm run test:e2e -- user-authentication.spec.ts`
- [ ] ✅ Test passes (green phase)
### Test: Display Error for Invalid Credentials
- [ ] Add error state management
- [ ] Display error message UI
- [ ] Add `data-testid="error-message"`
- [ ] Run test: `npm run test:e2e -- user-authentication.spec.ts`
- [ ] ✅ Test passes (green phase)
### Test: Redirect to Dashboard After Login
- [ ] Implement redirect logic after successful auth
- [ ] Verify authentication token stored
- [ ] Add dashboard route protection
- [ ] Run test: `npm run test:e2e -- user-authentication.spec.ts`
- [ ] ✅ Test passes (green phase)
## Running Tests
```bash
# Run all failing tests
npm run test:e2e
# Run specific test file
npm run test:e2e -- user-authentication.spec.ts
# Run tests in headed mode (see browser)
npm run test:e2e -- --headed
# Debug specific test
npm run test:e2e -- user-authentication.spec.ts --debug
```
Red-Green-Refactor Workflow
RED Phase (Complete):
- ✅ All tests written and failing
 - ✅ Fixtures and factories created
 - ✅ data-testid requirements documented
 
GREEN Phase (DEV Team - Next Steps):
- Pick one failing test from checklist
 - Implement minimal code to make it pass
 - Run test to verify green
 - Check off task in checklist
 - Move to next test
 - Repeat until all tests pass
 
REFACTOR Phase (DEV Team - After All Tests Pass):
- All tests passing (green)
 - Improve code quality (extract functions, optimize)
 - Remove duplications
 - Ensure tests still pass after each refactor
 
Next Steps
- Review this checklist with team
 - Run failing tests to confirm RED phase: 
npm run test:e2e - Begin implementation using checklist as guide
 - Share progress in daily standup
 - When all tests pass, run 
bmad sm story-doneto move story to DONE 
This comprehensive checklist guides DEV team from red to green with clear tasks and validation steps.