How to Run ATDD with TEA
How to Run ATDD with TEA
Section titled âHow to Run ATDD with TEAâUse TEAâs atdd workflow to generate red-phase acceptance test scaffolds BEFORE implementation. TEA currently emits these scaffolds with test.skip() so they can be reviewed, linked into the story, and activated task-by-task during implementation.
When to Use This
Section titled âWhen to Use Thisâ- Youâre about to implement a NEW feature (feature doesnât exist yet)
- You want to follow TDD workflow (red â green â refactor)
- You want tests to guide your implementation
- Youâre practicing acceptance test-driven development
Donât use this if:
- Feature already exists (use
automateinstead) - You want tests that pass immediately
Prerequisites
Section titled âPrerequisitesâ- BMad Method installed
- TEA agent available
- Test framework setup complete (run
frameworkif needed) - Story or feature defined with acceptance criteria
Note: This guide uses Playwright examples. If using Cypress, commands and syntax will differ (e.g., cy.get() instead of page.locator()).
1. Load TEA Agent
Section titled â1. Load TEA AgentâStart a fresh chat and load TEA:
tea2. Run the ATDD Workflow
Section titled â2. Run the ATDD Workflowâatdd3. Provide Context
Section titled â3. Provide ContextâTEA will ask for:
Story/Feature Details:
We're adding a user profile page where users can:- View their profile information- Edit their name and email- Upload a profile picture- Save changes with validationAcceptance Criteria:
Given I'm logged inWhen I navigate to /profileThen I see my current name and email
Given I'm on the profile pageWhen I click "Edit Profile"Then I can modify my name and email
Given I've edited my profileWhen I click "Save"Then my changes are persistedAnd I see a success message
Given I upload an invalid file typeWhen I try to saveThen I see an error messageAnd changes are not savedReference Documents (optional):
- Point to your story file
- Reference PRD or tech spec
- Link to test design (if you ran
test-designfirst)
4. Specify Test Levels
Section titled â4. Specify Test LevelsâTEA will ask what test levels to generate:
Options:
- E2E tests (browser-based, full user journey)
- API tests (backend only, faster)
- Component tests (UI components in isolation)
- Mix of levels (see API Tests First, E2E Later tip)
Component Testing by Framework
Section titled âComponent Testing by FrameworkâTEA generates component tests using framework-appropriate tools:
| Your Framework | Component Testing Tool |
|---|---|
| Cypress | Cypress Component Testing (*.cy.tsx) |
| Playwright | Vitest + React Testing Library (*.test.tsx) |
Example response:
Generate:- API tests for profile CRUD operations- E2E tests for the complete profile editing flow- Component tests for ProfileForm validation (if using Cypress or Vitest)- Focus on P0 and P1 scenarios5. Review Generated Tests
Section titled â5. Review Generated TestsâTEA generates red-phase test scaffolds in appropriate directories:
API Tests (tests/api/profile.spec.ts):
Section titled âAPI Tests (tests/api/profile.spec.ts):âVanilla Playwright:
import { test, expect } from '@playwright/test';
test.describe('Profile API', () => { test.skip('should fetch user profile', async ({ request }) => { const response = await request.get('/api/profile');
expect(response.status()).toBe(200); const profile = await response.json(); expect(profile).toHaveProperty('name'); expect(profile).toHaveProperty('email'); expect(profile).toHaveProperty('avatarUrl'); });
test.skip('should update user profile', async ({ request }) => { const response = await request.patch('/api/profile', { data: { name: 'Updated Name', email: 'updated@example.com', }, });
expect(response.status()).toBe(200); const updated = await response.json(); expect(updated.name).toBe('Updated Name'); expect(updated.email).toBe('updated@example.com'); });
test.skip('should validate email format', async ({ request }) => { const response = await request.patch('/api/profile', { data: { email: 'invalid-email', }, });
expect(response.status()).toBe(400); const error = await response.json(); expect(error.message).toContain('Invalid email format'); });});With Playwright Utils:
import { test } from '@seontechnologies/playwright-utils/api-request/fixtures';import { expect } from '@playwright/test';import { z } from 'zod';
const ProfileSchema = z.object({ name: z.string(), email: z.string().email(), avatarUrl: z.string().url(),});
test.describe('Profile API', () => { test.skip('should fetch user profile', async ({ apiRequest }) => { const { status, body } = await apiRequest({ method: 'GET', path: '/api/profile', }).validateSchema(ProfileSchema); // Chained validation
expect(status).toBe(200); // Schema already validated, type-safe access expect(body.name).toBeDefined(); expect(body.email).toContain('@'); });
test.skip('should update user profile', async ({ apiRequest }) => { const { status, body } = await apiRequest({ method: 'PATCH', path: '/api/profile', body: { name: 'Updated Name', email: 'updated@example.com', }, }).validateSchema(ProfileSchema); // Chained validation
expect(status).toBe(200); expect(body.name).toBe('Updated Name'); expect(body.email).toBe('updated@example.com'); });
test.skip('should validate email format', async ({ apiRequest }) => { const { status, body } = await apiRequest({ method: 'PATCH', path: '/api/profile', body: { email: 'invalid-email' }, });
expect(status).toBe(400); expect(body.message).toContain('Invalid email format'); });});Key Benefits:
- Returns
{ status, body }(cleaner thanresponse.status()+await response.json()) - Automatic schema validation with Zod
- Type-safe response bodies
- Automatic retry for 5xx errors
- Less boilerplate
E2E Tests (tests/e2e/profile.spec.ts):
Section titled âE2E Tests (tests/e2e/profile.spec.ts):âimport { test, expect } from '@playwright/test';
test.skip('should edit and save profile', async ({ page }) => { // Login first await page.goto('/login'); await page.getByLabel('Email').fill('test@example.com'); await page.getByLabel('Password').fill('password123'); await page.getByRole('button', { name: 'Sign in' }).click();
// Navigate to profile await page.goto('/profile');
// Edit profile await page.getByRole('button', { name: 'Edit Profile' }).click(); await page.getByLabel('Name').fill('Updated Name'); await page.getByRole('button', { name: 'Save' }).click();
// Verify success await expect(page.getByText('Profile updated')).toBeVisible();});TEA generates additional E2E tests for display, validation errors, etc. based on acceptance criteria.
Implementation Checklist
Section titled âImplementation ChecklistâTEA also provides an implementation checklist:
## Implementation Checklist
### Backend
- [ ] Create `GET /api/profile` endpoint- [ ] Create `PATCH /api/profile` endpoint- [ ] Add email validation middleware- [ ] Add profile picture upload handling- [ ] Write API unit tests
### Frontend
- [ ] Create ProfilePage component- [ ] Implement profile form with validation- [ ] Add file upload for avatar- [ ] Handle API errors gracefully- [ ] Add loading states
### Tests
- [x] API test scaffolds generated (`test.skip()`)- [x] E2E test scaffolds generated (`test.skip()`)- [ ] Activate and run tests during implementation (should fail before code changes, then pass)6. Verify Red-Phase Scaffolds
Section titled â6. Verify Red-Phase ScaffoldsâThis is the TDD red phase, but TEA keeps generated tests in test.skip() until youâre ready to work on a task. Review the generated files, then remove test.skip() for the current task and confirm that the newly activated test fails before you implement the feature.
For Playwright:
npx playwright testFor Cypress:
npx cypress runInitial output with scaffolds still skipped:
Running 6 tests using 1 worker
- tests/api/profile.spec.ts:3:3 âș should fetch user profile - tests/api/profile.spec.ts:15:3 âș should update user profile - tests/e2e/profile.spec.ts:10:3 âș should edit and save profile
6 skippedAfter you remove test.skip() from the task you are implementing, that activated test should fail first. This confirms:
- Feature doesnât exist yet
- Tests will guide implementation
- You have clear success criteria
7. Implement the Feature
Section titled â7. Implement the FeatureâNow implement the feature following the test guidance:
- Start with API tests (backend first)
- Remove
test.skip()from the first API test and confirm RED - Implement until that test passes
- Move to the next API or E2E test and repeat
- Refactor with confidence (tests protect you)
8. Verify Tests Pass
Section titled â8. Verify Tests PassâAfter implementation, run your test suite.
For Playwright:
npx playwright testFor Cypress:
npx cypress runExpected output:
Running 6 tests using 1 worker
â tests/api/profile.spec.ts:3:3 âș should fetch user profile (850ms) â tests/api/profile.spec.ts:15:3 âș should update user profile (1.2s) â tests/api/profile.spec.ts:30:3 âș should validate email format (650ms) â tests/e2e/profile.spec.ts:10:3 âș should display current profile (2.1s) â tests/e2e/profile.spec.ts:18:3 âș should edit and save profile (3.2s) â tests/e2e/profile.spec.ts:35:3 âș should show validation error (1.8s)
6 passed (9.8s)Green! Youâve completed the active red â green â refactor cycle for the generated scaffolds.
What You Get
Section titled âWhat You GetâRed-Phase Test Scaffolds
Section titled âRed-Phase Test Scaffoldsâ- API tests for backend endpoints
- E2E tests for user workflows
- Component tests (if requested)
- Generated with
test.skip()until you activate them task-by-task
Implementation Guidance
Section titled âImplementation Guidanceâ- Clear checklist of what to build
- Acceptance criteria translated to assertions
- Edge cases and error scenarios identified
TDD Workflow Support
Section titled âTDD Workflow Supportâ- Activated tests guide implementation
- Confidence to refactor
- Living documentation of features
Start with Test Design
Section titled âStart with Test DesignâRun test-design before atdd for better results:
test-design # Risk assessment and prioritiesatdd # Generate tests based on designBrowser Automation (Optional)
Section titled âBrowser Automation (Optional)âIf browser automation is configured (tea_browser_automation: "auto" or "cli" or "mcp"), TEA can verify selectors against live browsers during atdd.
- CLI mode: Takes snapshots to verify element names and roles before generating selectors
- MCP mode: Full browser automation for complex UI interactions
- Auto mode: Uses CLI for simple verification, MCP for complex flows
Note: ATDD is for features that donât exist yet, so browser verification only applies if you have skeleton/mockup UI already implemented. For typical ATDD (no UI yet), TEA infers selectors from best practices.
See Configure Browser Automation for setup.
Focus on P0/P1 Scenarios
Section titled âFocus on P0/P1 ScenariosâDonât generate tests for everything at once:
Generate tests for:- P0: Critical path (happy path)- P1: High value (validation, errors)
Skip P2/P3 for now - add later with automateAPI Tests First, E2E Later
Section titled âAPI Tests First, E2E LaterâRecommended order:
- Generate API tests with
atdd - Implement backend (make API tests pass)
- Generate E2E tests with
atdd(orautomate) - Implement frontend (make E2E tests pass)
This âoutside-inâ approach is faster and more reliable.
Keep Tests Deterministic
Section titled âKeep Tests DeterministicâTEA generates deterministic tests by default:
- No hard waits (
waitForTimeout) - Network-first patterns (wait for responses)
- Explicit assertions (no conditionals)
Donât modify these patterns - they prevent flakiness!
Related Guides
Section titled âRelated Guidesâ- How to Run Test Design - Plan before generating
- How to Run Automate - Tests for existing features
- How to Set Up Test Framework - Initial setup
Understanding the Concepts
Section titled âUnderstanding the Conceptsâ- Testing as Engineering - Why TEA generates quality tests (foundational)
- Risk-Based Testing - Why P0 vs P3 matters
- Test Quality Standards - What makes tests good
- Network-First Patterns - Avoiding flakiness
Reference
Section titled âReferenceâ- Command: *atdd - Full command reference
- TEA Configuration - MCP and Playwright Utils options
Generated with BMad Method - TEA (Test Engineering Architect)