How to Run Automate with TEA
How to Run Automate with TEA
Section titled “How to Run Automate with TEA”Use the Automate skill’s expand mode to add tests for implemented features. It also supports red mode for acceptance scaffolds before implementation. Your prompt selects the mode; the automate command and TA menu code default to expand.
Create runs execute the generated tests and repair test issues by default, for up to three rounds. The summary records the repairs and any remaining failures. Real product defects keep their failing assertions and appear as findings.
For unattended generation and JSON outcomes, use the tea-automate CLI. It supports red and expand, saved-run continuation, validation, and edits.
Choose red mode before implementation or expand mode for existing code. Both modes support Create, Resume, Validate, and Edit. Each keeps its customization files and saved progress.
Quick Path
Section titled “Quick Path”- Request. Invoke the skill and say what to cover, for example
Expand coverage for story-profile-management.md: API tests for P0 and P1, one E2E test for the P0 journey. - Let it run. TEA generates the tests, runs them, and repairs test issues for up to three rounds.
- Read the summary.
{test_artifacts}/automate/automation-summary-{run_key}.mdlists the files added, the repairs, and any remaining failures; a product defect keeps its failing assertion. - Verify. Run the suite with your project’s test command and review the diff before you commit.
The sections below cover each step’s options, with examples.
Expand Mode
Section titled “Expand Mode”When to Use This
Section titled “When to Use This”- Feature already exists and works
- Want to add test coverage to existing code
- Expanding existing test suite
- Adding tests to legacy code
For acceptance tests before implementation, use red mode.
Prerequisites
Section titled “Prerequisites”- Test framework setup complete (run
frameworkif needed) - Feature implemented and working
This guide uses Playwright examples. If using Cypress, commands and syntax will differ.
1. Run the Automate Skill
Section titled “1. Run the Automate Skill”- Claude Code / Cursor / Windsurf:
/bmad-tea-automate - Codex:
$bmad-tea-automate - Inside a
/bmad-teachat:TA
Acceptance scaffolds before implementation select red; coverage for existing code selects expand. With no task mode signal, Automate and TA default to expand. Conflicting task mode signals prompt one mode question in an interactive run; an unattended run uses expand. Every default fallback states the selected mode in the final summary. Existing customization files and interrupted progress remain usable.
Full invocation rules: Invoking a TEA Skill.
2. Provide Context
Section titled “2. Provide Context”TEA will ask for context about what you’re testing.
Option A: BMad-Integrated Mode (Recommended)
Section titled “Option A: BMad-Integrated Mode (Recommended)”If you have BMad artifacts (stories, test designs, PRDs):
What are you testing?
I'm testing the user profile feature we just implemented.Story: story-profile-management.mdTest Design: test-design/test-design-epic-1.mdReference documents:
- Story file with acceptance criteria
- Test design document (if available)
- PRD sections relevant to this feature
- Tech spec (if available)
Existing tests:
We have basic tests in tests/e2e/profile-view.spec.tsAvoid duplicating that coverageTEA will analyze your artifacts and generate tests that:
- Cover acceptance criteria from the story
- Follow priorities from test design (P0 → P1 → P2)
- Avoid duplicating existing tests
- Include edge cases and error scenarios
Option B: Standalone Mode
Section titled “Option B: Standalone Mode”If you’re using TEA Solo or don’t have BMad artifacts:
What are you testing?
TodoMVC React application at https://todomvc.com/examples/react/dist/Features: Create todos, mark as complete, filter by status, delete todosSpecific scenarios to cover:
- Creating todos (happy path)- Marking todos as complete/incomplete- Filtering (All, Active, Completed)- Deleting todos- Edge cases (empty input, long text)TEA will analyze the application and generate tests based on your description.
3. Specify Test Levels
Section titled “3. Specify Test Levels”TEA will ask which test levels to generate:
Options:
- E2E tests: Full browser-based user workflows
- API tests: Backend endpoint testing (faster, more reliable)
- Component tests: UI component testing in isolation (framework-dependent)
- Mix: Combination of levels (recommended)
Example response:
Generate:- API tests for all CRUD operations- E2E tests for critical user workflows (P0)- Focus on P0 and P1 scenarios- Skip P3 (low priority edge cases)4. Review Generated Tests
Section titled “4. Review Generated Tests”TEA generates a test suite with multiple test levels.
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', () => { let authToken: string;
test.beforeAll(async ({ request }) => { // Manual auth token fetch const response = await request.post('/api/auth/login', { data: { email: 'test@example.com', password: 'password123' }, }); const { token } = await response.json(); authToken = token; });
test('should fetch user profile', async ({ request }) => { const response = await request.get('/api/profile', { headers: { Authorization: `Bearer ${authToken}` }, });
expect(response.ok()).toBeTruthy(); const profile = await response.json(); expect(profile).toMatchObject({ id: expect.any(String), name: expect.any(String), email: expect.any(String), }); });
test('should update profile successfully', async ({ request }) => { const response = await request.patch('/api/profile', { headers: { Authorization: `Bearer ${authToken}` }, data: { name: 'Updated Name', bio: 'Test bio', }, });
expect(response.ok()).toBeTruthy(); const updated = await response.json(); expect(updated.name).toBe('Updated Name'); expect(updated.bio).toBe('Test bio'); });
test('should validate email format', async ({ request }) => { const response = await request.patch('/api/profile', { headers: { Authorization: `Bearer ${authToken}` }, data: { email: 'invalid-email' }, });
expect(response.status()).toBe(400); const error = await response.json(); expect(error.message).toContain('Invalid email'); });
test('should require authentication', async ({ request }) => { const response = await request.get('/api/profile'); expect(response.status()).toBe(401); });});With Playwright Utils: the spec imports the shared module, which merges the API and auth fixtures (setup).
import { test, expect } from '../support/merged-fixtures';import { z } from 'zod';
const ProfileSchema = z.object({ id: z.string(), name: z.string(), email: z.string().email(),});
test.describe('Profile API', () => { test('should fetch user profile', async ({ apiRequest, authToken }) => { const { status, body } = await apiRequest({ method: 'GET', path: '/api/profile', headers: { Authorization: `Bearer ${authToken}` }, }).validateSchema(ProfileSchema); // Chained validation
expect(status).toBe(200); // Schema already validated, type-safe access expect(body.name).toBeDefined(); });
test('should update profile successfully', async ({ apiRequest, authToken }) => { const { status, body } = await apiRequest({ method: 'PATCH', path: '/api/profile', body: { name: 'Updated Name', bio: 'Test bio' }, headers: { Authorization: `Bearer ${authToken}` }, }).validateSchema(ProfileSchema); // Chained validation
expect(status).toBe(200); expect(body.name).toBe('Updated Name'); });
test('should validate email format', async ({ apiRequest, authToken }) => { const { status, body } = await apiRequest({ method: 'PATCH', path: '/api/profile', body: { email: 'invalid-email' }, headers: { Authorization: `Bearer ${authToken}` }, });
expect(status).toBe(400); expect(body.message).toContain('Invalid email'); });});apiRequest returns { status, body }, supports chained Zod validation, and retries 5xx responses.
Use retryConfig: { maxRetries: 0 } when testing a server-error response.
E2E Tests (tests/e2e/profile.spec.ts):
Section titled “E2E Tests (tests/e2e/profile.spec.ts):”import { test, expect } from '@playwright/test';
test('should edit profile', async ({ page }) => { // Login 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();
// Edit profile await page.goto('/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(); await page.reload(); await page.getByRole('button', { name: 'Edit Profile' }).click(); await expect(page.getByLabel('Name')).toHaveValue('Updated Name');});TEA generates validation and edge-case tests according to the priorities you supplied.
Fixtures (tests/support/fixtures/profile.ts):
Section titled “Fixtures (tests/support/fixtures/profile.ts):”Vanilla Playwright:
import { test as base, Page } from '@playwright/test';
type ProfileFixtures = { authenticatedPage: Page; testProfile: { name: string; email: string; bio: string; };};
export const test = base.extend<ProfileFixtures>({ authenticatedPage: async ({ page }, use) => { // Manual login flow 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(); await page.waitForURL(/\/dashboard/);
await use(page); },
testProfile: async ({ request }, use) => { // Static test data const profile = { name: 'Test User', email: 'test@example.com', bio: 'Test bio', };
await use(profile); },});With Playwright Utils: the custom fixture lives in its own file and joins the shared module, so specs keep one entry point.
import { test as base } from '@playwright/test';import { faker } from '@faker-js/faker';
type ProfileFixtures = { testProfile: { name: string; email: string; bio: string };};
export const test = base.extend<ProfileFixtures>({ testProfile: async ({}, use) => { // Dynamic test data with faker await use({ name: faker.person.fullName(), email: faker.internet.email(), bio: faker.person.bio(), }); },});// tests/support/merged-fixtures.ts: add the fixture to the existing mergeTests callimport { test as profileFixture } from './fixtures/profile-fixture';
export const test = mergeTests(apiRequestFixture, authFixture, profileFixture /* , ... */);Usage:
import { test, expect } from '../support/merged-fixtures';
test('should update profile', async ({ apiRequest, authToken, testProfile }) => { const { status } = await apiRequest({ method: 'PATCH', path: '/api/profile', body: testProfile, headers: { Authorization: `Bearer ${authToken}` }, });
expect(status).toBe(200);});authToken is the Bearer token for API requests. The merged auth-session fixtures also open page with the storage state the auth provider saved, so a browser test starts signed in once the provider performs a real sign-in; see auth-session.
Add cleanup if the test creates persistent records.
5. Review Additional Artifacts
Section titled “5. Review Additional Artifacts”TEA also generates:
Updated README (tests/README.md):
Section titled “Updated README (tests/README.md):”# Test Suite
## Running Tests
### All Tests
npm test
### Specific Levels
npm run test:api # API tests onlynpm run test:e2e # E2E tests onlynpm run test:smoke # Smoke tests (@smoke tag)
### Single File
npx playwright test tests/api/profile.spec.ts
## Test Structure
tests/├── api/ # API tests (fast, reliable)├── e2e/ # E2E tests (full workflows)├── support/ # merged-fixtures.ts, fixtures, helpers└── README.md
## Writing Tests
Follow the patterns in existing tests:
- Use fixtures for authentication- Network-first patterns (no hard waits)- Explicit assertions- Self-cleaning testsDefinition of Done Summary:
Section titled “Definition of Done Summary:”The checklist is part of the automation summary at {test_artifacts}/automate/automation-summary-{run_key}.md.
The run_key names the scope: story-{story_key} or epic-{epic_num} when you name a story or epic, target-{slug} for a feature or path with neither, and system for a run across the whole codebase.
## Test Quality Checklist
✅ All tests pass on first run✅ No hard waits (waitForTimeout)✅ No conditionals for flow control✅ Assertions are explicit✅ Tests clean up after themselves✅ Tests can run in parallel✅ Execution time < 1.5 minutes per test✅ Test files ≤ 1000 lines6. Run the Tests
Section titled “6. Run the Tests”Run the generated tests against the implemented feature:
npm run test:e2e # Playwright via TEA's framework scaffold, which carries the config pathnpx cypress run # CypressExample output; the counts depend on the scope you requested:
Running 6 tests using 4 workers
✓ tests/api/profile.spec.ts (4 tests) - 2.1s ✓ tests/e2e/profile-workflow.spec.ts (2 tests) - 5.3s
6 passed (7.4s)Investigate each failure: it can reveal a product defect, an incorrect assertion, or missing test setup.
7. Review Test Coverage
Section titled “7. Review Test Coverage”Check which scenarios are covered:
npx playwright show-reportFor code coverage, use whatever your project already has.
TEA’s framework skill does not add a coverage script.
Compare against:
- Acceptance criteria from story
- Test priorities from test design
- Edge cases and error scenarios
What You Get
Section titled “What You Get”Test Suite
Section titled “Test Suite”- API tests: Fast, reliable backend testing
- E2E tests: Critical user workflows
- Component tests: UI component testing (if requested)
- Fixtures: Shared utilities and setup
Component Testing by Framework
Section titled “Component Testing by Framework”TEA supports component testing using framework-appropriate tools:
| Your Framework | Component Testing Tool | Tests Location |
|---|---|---|
| Cypress | Cypress Component Testing | tests/component/ |
| Playwright | Vitest + React Testing Library | tests/component/ or src/**/*.test.tsx |
Component tests use separate tooling from E2E tests:
- Cypress users: TEA generates Cypress Component Tests
- Playwright users: TEA generates Vitest + React Testing Library tests
Quality Features
Section titled “Quality Features”- Network-first patterns: Wait for the response a user action triggers
- Deterministic tests: Explicit assertions and controlled setup
- Self-cleaning: Tests don’t leave test data behind
- Parallel-safe setup: Isolated data for concurrent runs
Documentation
Section titled “Documentation”- Updated README: How to run tests
- Test structure explanation: Where tests live
- Definition of Done: Quality standards
Start with Test Design
Section titled “Start with Test Design”Run test-design before automate for better results:
/bmad-tea-test-design # risk assessment, priorities/bmad-tea-automate # generate tests based on those prioritiesTEA will focus on P0/P1 scenarios and skip low-value tests.
Prioritize Test Levels
Section titled “Prioritize Test Levels”Not everything needs E2E tests:
Good strategy:
- P0 scenarios: API + E2E tests # reserve E2E for critical user journeys- P1 scenarios: API tests only # API tests run ~10x faster, no browser flakiness- P2 scenarios: API tests (happy path)- P3 scenarios: Skip or add laterAvoid Duplicate Coverage
Section titled “Avoid Duplicate Coverage”Tell TEA about existing tests:
We already have tests in:- tests/e2e/profile-view.spec.ts (viewing profile)- tests/api/auth.spec.ts (authentication)
Don't duplicate that coverageTEA will analyze existing tests and only generate new scenarios.
Run and Heal
Section titled “Run and Heal”Create runs execute the generated tests, classify failures, apply the matching test fixes, and rerun up to three rounds. Selector failures use resilient locators; timing and hard-wait failures use observable readiness; data and network failures use controlled fixtures and request handling. A real product defect remains a finding with the assertion intact. The run reports blocked execution when its environment cannot run the tests.
Validate checks the selected outputs and reports execution evidence. Edit checks the requested changes. These operations never run test repairs or require the full suite to pass.
Run and heal is enabled by default. Customize auto_validate, auto_heal_failures, max_healing_iterations, and use_mcp_healing in the automation settings.
Browser Automation (Optional)
Section titled “Browser Automation (Optional)”If browser automation is configured (tea_browser_automation: "auto" or "cli" or "mcp"), TEA can use browser tools during automate for:
- Healing mode: Fix broken selectors using CLI snapshots or MCP DOM analysis
- Recording mode: Verify selectors with CLI snapshots or MCP browser, capture network requests
- Evidence capture: CLI traces and screenshots for test validation
TEA uses browser tools automatically when available and appropriate; it does not prompt.
See Configure Browser Automation for setup.
Generate Tests Incrementally
Section titled “Generate Tests Incrementally”Don’t generate all tests at once:
Run 1: P0 tests only (critical path)Run 2: P1 tests (high value scenarios); avoid duplicating P0 coverageRun 3: P2 tests (if time permits)Run and review each batch before generating the next one.
Common Issues
Section titled “Common Issues”Tests Pass But Coverage Is Incomplete
Section titled “Tests Pass But Coverage Is Incomplete”Tests pass but don’t cover all scenarios.
TEA wasn’t given complete context.
Provide more details:
Generate tests for:- All acceptance criteria in story-profile.md- Error scenarios (validation, authorization)- Edge cases (empty fields, long inputs)Too Many Tests Generated
Section titled “Too Many Tests Generated”TEA generated 50 tests for a simple feature.
Didn’t specify priorities or scope.
Be specific:
Generate ONLY:- P0 and P1 scenarios- API tests for all scenarios- E2E tests only for critical workflows- Skip P2/P3 for nowTests Duplicate Existing Coverage
Section titled “Tests Duplicate Existing Coverage”New tests cover the same scenarios as existing tests.
Didn’t tell TEA about existing tests.
Specify existing coverage:
We already have these tests:- tests/api/profile.spec.ts (GET /api/profile)- tests/e2e/profile-view.spec.ts (viewing profile)
Generate tests for scenarios NOT covered by those filesRelated Guides
Section titled “Related Guides”- How to Run Test Design: Plan before generating
- Automate Red Mode: Failing tests before implementation
- How to Run Test Review: Audit generated quality
Understanding the Concepts
Section titled “Understanding the Concepts”- Testing as Engineering: Why TEA generates quality tests (foundational)
- Risk-Based Testing: Why prioritize P0 over P3
- Test Quality Standards: What makes tests good
- Fixture Architecture: Reusable test patterns
Reference
Section titled “Reference”- Command: automate: Full command reference
- TEA Configuration: MCP and Playwright Utils options
Red Mode
Section titled “Red Mode”Use the Automate skill’s red mode to generate acceptance test scaffolds before implementation. Ask /bmad-tea-automate, $bmad-tea-automate, or TA for red mode.
TEA 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 are about to implement a feature
- You want to follow TDD workflow (red → green → refactor)
- You want tests to guide your implementation
- You’re practicing acceptance test-driven development
For tests of implemented features, use Automate.
Prerequisites
Section titled “Prerequisites”- Test framework setup complete (run
frameworkif needed) - Story or feature defined with acceptance criteria
The examples use Playwright. Adapt the commands and selectors for Cypress.
1. Run Automate in Red Mode
Section titled “1. Run Automate in Red Mode”- Claude Code / Cursor / Windsurf:
/bmad-tea-automate - Codex:
$bmad-tea-automate - Inside a
/bmad-teachat:TA
Request red mode explicitly:
Generate red acceptance scaffolds for this story before implementation.Acceptance scaffolds before implementation select red; coverage for existing code selects expand. With no task mode signal, Automate and TA default to expand. Conflicting task mode signals prompt one mode question in an interactive run; an unattended run uses expand. Every default fallback states the selected mode in the final summary. Existing customization files and interrupted ATDD progress remain usable.
Create runs verify the generated tests in a disposable copy with their scaffold skips activated. TEA uses tea-atdd-red-check for compatible browserless loopback Playwright tests when the command is installed, and tea-unit-check for Vitest and Jest scaffolds. Browser tests and projects needing their own environment or services use the installed project test runner with the original configuration and environment. Execution respects the project’s existing test budgets, and the summary names the runner and any fallback reason. Tests must fail for the acceptance behavior that implementation will add. TEA repairs syntax, imports, selectors, data, timing, network, hard waits, and setup that cause the wrong failure, for up to three rounds. The implementation handoff retains its deliberate skipped scaffolds. The summary records repairs, intended red failures, and unresolved problems. Validate reports findings and Edit checks the changes you requested; neither operation repairs tests.
Full invocation rules: Invoking a TEA Skill.
2. Provide Context
Section titled “2. 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 enter an invalid email addressWhen I try to saveThen the update returns status 400And the error message contains "Invalid email format"TEA builds a criterion registry before it generates tests.
Existing AC-<n> ids remain unchanged.
For criteria without ids, TEA reserves the supplied ids, visits unnamed criteria in source order, and assigns each the lowest unused AC-<n> id.
Every executable test title carries exactly one id from that registry.
TEA emits exactly one red-phase leaf scaffold per declared criterion. Secondary branches and journeys remain implementation-checklist work until green-phase automation. Each scaffold puts one direct criterion assertion first. That assertion isolates the exact newly promised status, scalar, or property before broad object, schema, or secondary checks. API setup calls to unimplemented endpoints keep their responses opaque until this assertion runs. E2E scaffolds place the complete browser journey inside the first potentially failing assertion boundary.
Reference Documents (optional):
- Point to your story file
- Reference PRD or tech spec
- Link to test design (if you ran
test-designfirst)
3. Specify Test Levels
Section titled “3. 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 scenarios4. Review Generated Tests
Section titled “4. 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):”Both API variants import the project’s existing fixture entry point, which exports test with an authToken fixture for the seeded test@example.com user: tests/support/fixtures.ts in vanilla Playwright, tests/support/merged-fixtures.ts with Playwright Utils.
The fixture must supply a valid Bearer token through the working authentication flow before profile scaffolds are activated.
Verify authentication independently and report fixture setup failures as prerequisite failures; criterion red evidence comes from the profile response’s first status assertion.
For Playwright Utils, build that auth fixture with a registered provider and createAuthFixtures() and merge it into the module, as auth-session shows.
The examples reuse that fixture and send its token on every profile request.
Vanilla Playwright:
import { test } from '../support/fixtures';import { expect } from '@playwright/test';
test.describe('Profile API', () => { test.skip('[P0] AC-1 should fetch user profile', async ({ request, authToken }) => { const response = await request.get('/api/profile', { headers: { Authorization: `Bearer ${authToken}` }, });
expect(response.status()).toBe(200); const profile = await response.json(); expect(profile).toHaveProperty('name'); expect(profile).toHaveProperty('email'); expect(profile).toHaveProperty('avatarUrl'); });
test.skip('[P0] AC-2 should update user profile', async ({ request, authToken }) => { const response = await request.patch('/api/profile', { headers: { Authorization: `Bearer ${authToken}` }, 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('[P1] AC-4 should validate email format', async ({ request, authToken }) => { const response = await request.patch('/api/profile', { headers: { Authorization: `Bearer ${authToken}` }, 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, expect } from '../support/merged-fixtures';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('[P0] AC-1 should fetch user profile', async ({ apiRequest, authToken }) => { const { status, body } = await apiRequest({ method: 'GET', path: '/api/profile', headers: { Authorization: `Bearer ${authToken}` }, });
expect(status).toBe(200); const profile = ProfileSchema.parse(body); expect(profile.name).toBeDefined(); expect(profile.email).toContain('@'); });
test.skip('[P0] AC-2 should update user profile', async ({ apiRequest, authToken }) => { const { status, body } = await apiRequest({ method: 'PATCH', path: '/api/profile', headers: { Authorization: `Bearer ${authToken}` }, body: { name: 'Updated Name', email: 'updated@example.com', }, });
expect(status).toBe(200); const updated = ProfileSchema.parse(body); expect(updated.name).toBe('Updated Name'); expect(updated.email).toBe('updated@example.com'); });
test.skip('[P1] AC-4 should validate email format', async ({ apiRequest, authToken }) => { const { status, body } = await apiRequest({ method: 'PATCH', path: '/api/profile', headers: { Authorization: `Bearer ${authToken}` }, body: { email: 'invalid-email' }, });
expect(status).toBe(400); expect(body.message).toContain('Invalid email format'); });});apiRequest returns { status, body } and supports chained Zod validation.
Disable retries with retryConfig: { maxRetries: 0 } for tests that assert a 5xx response.
E2E Tests (tests/e2e/profile.spec.ts):
Section titled “E2E Tests (tests/e2e/profile.spec.ts):”import { test, expect } from '@playwright/test';
test.skip('[P0] AC-3 should edit and save profile', async ({ page }) => { // This assertion is the first potentially failing operation. Every browser // failure in the journey retains AC-3 provenance. await expect( (async () => { 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(); await page.goto('/profile'); await page.getByRole('button', { name: 'Edit Profile' }).click(); await page.getByLabel('Name').fill('Updated Name'); await page.getByRole('button', { name: 'Save' }).click(); await expect(page.getByText('Profile updated')).toBeVisible(); await page.reload(); await page.getByRole('button', { name: 'Edit Profile' }).click(); await expect(page.getByLabel('Name')).toHaveValue('Updated Name'); })(), ).resolves.toBeUndefined();});TEA records additional display, validation-error, and other secondary E2E journeys in the implementation checklist for green-phase automation.
Implementation Checklist
Section titled “Implementation Checklist”TEA also provides an implementation checklist, saved as {test_artifacts}/atdd/atdd-checklist-{story_key}.md (for example atdd-checklist-1-2-user-authentication.md):
## 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)5. Verify Red-Phase Scaffolds
Section titled “5. Verify Red-Phase Scaffolds”TEA verifies the TDD red phase using an isolated, un-skipped copy. The saved scaffolds keep 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.
npm run test:e2e # Playwright via TEA's framework scaffold, which carries the config pathnpx cypress run # CypressExample initial output with scaffolds still skipped:
Running 4 tests using 1 worker
- tests/api/profile.spec.ts:3:3 › [P0] AC-1 should fetch user profile - tests/api/profile.spec.ts:15:3 › [P0] AC-2 should update user profile - tests/api/profile.spec.ts:30:3 › [P1] AC-4 should validate email format - tests/e2e/profile.spec.ts:18:3 › [P0] AC-3 should edit and save profile
4 skippedAfter you remove test.skip(), confirm the test fails at the assertion for the promised behavior.
A setup failure needs repair before implementation starts.
6. Implement the Feature
Section titled “6. 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)
7. Verify Tests Pass
Section titled “7. Verify Tests Pass”After implementation, run your test suite with the same command. Example output:
Running 4 tests using 1 worker
✓ tests/api/profile.spec.ts:3:3 › [P0] AC-1 should fetch user profile (850ms) ✓ tests/api/profile.spec.ts:15:3 › [P0] AC-2 should update user profile (1.2s) ✓ tests/api/profile.spec.ts:30:3 › [P1] AC-4 should validate email format (650ms) ✓ tests/e2e/profile.spec.ts:18:3 › [P0] AC-3 should edit and save profile (3.2s)
4 passed (5.9s)That completes the 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 Automate red mode for better results:
/bmad-tea-test-design # risk assessment and priorities/bmad-tea-automate # request red mode to generate tests based on that 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 Automate red mode.
- 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
Red mode is for features that don’t exist yet, so browser verification only applies if you have skeleton/mockup UI already implemented. For red mode with 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 them later with Automate expand mode.API Tests First, E2E Later
Section titled “API Tests First, E2E Later”Recommended order:
- Generate API tests with Automate red mode
- Implement backend (make API tests pass)
- Generate E2E tests with Automate red mode for missing behavior or expand mode for implemented behavior
- Implement frontend (make E2E tests pass)
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)
Preserve response waits and explicit assertions when editing the generated tests.
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