QA Engineer
The acceptance criteria are the test plan. You validate, triage, and sign off. You don't write from scratch.
What Changes, What Doesn't
When test cases are generated from acceptance criteria, the manual transcription work disappears — you're not copying requirements into test management, reformatting Given/When/Then into test steps, or building coverage maps from scratch. The test cases arrive structured, linked to their source requirements, and ready to review.
What you gain: speed and traceability. Test cases linked to the exact acceptance criteria they test make coverage gaps visible immediately. Changes to requirements propagate — when the PM updates acceptance criteria, the test cases can be regenerated from the updated source. What stays squarely with QA: triage judgment, regression coverage decisions, risk-based prioritization, and sign-off authority. The agent generates the stubs. You own the quality signal.
QA Workflow
Test cases are generated from the acceptance criteria in the repo. They arrive in your test management system linked to the backlog story, with steps derived directly from the acceptance criteria. You don't create these — they're ready when you arrive.
Create test cases in project PROJ from the Notification Banner
acceptance criteria in docs/work/<feature>/requirements.md.
Link them to PROJ-456.
The agent creates test management cases — for example, PROJ-TC-201 through PROJ-TC-204 — each with steps derived from the acceptance criteria, linked to the backlog story. You can also create cases manually; the key is that each case gets a PROJ-TC-XXX identifier that threads through the entire workflow.
You add: Awareness of what's coming. If you're involved early, you can flag acceptance criteria that won't produce useful test cases before they're generated.
When the design team generates a component from Figma, the agent also generates a .spec.ts file with Playwright tests tagged to the test case keys. Here's what a generated stub looks like:
test.describe('NotificationBanner', () => {
test('PROJ-TC-201: should display info variant with message', async ({ page }) => {
await page.goto('http://localhost:6006/?path=/story/notificationbanner--info');
await expect(page.getByRole('alert')).toBeVisible();
await expect(page.getByText('Your changes have been saved')).toBeVisible();
});
test('PROJ-TC-202: should display error variant with error message', async ({ page }) => {
await page.goto('http://localhost:6006/?path=/story/notificationbanner--error');
await expect(page.getByRole('alert')).toHaveAttribute('data-variant', 'error');
await expect(page.getByText('Something went wrong')).toBeVisible();
});
test('PROJ-TC-203: should dismiss when dismiss button clicked', async ({ page }) => {
await page.goto('http://localhost:6006/?path=/story/notificationbanner--dismissable');
await page.getByRole('button', { name: 'Dismiss notification' }).click();
await expect(page.getByRole('alert')).not.toBeVisible();
});
});
When reviewing a generated stub, check four things: selectors (are they targeting the right elements using accessible roles and labels?), assertions (do they actually verify the acceptance criterion, or are they too shallow?), story URLs (do the Storybook story paths match the actual story names?), and case key mapping (does each test title start with the correct PROJ-TC-XXX prefix?).
Then add what the agent didn't generate — this is where your expertise matters most. The agent covers the happy path from the acceptance criteria. You add edge cases, boundary conditions, interaction sequences, and error states:
// Edge case — the agent wouldn't generate this
test('PROJ-TC-205: should truncate messages longer than 120 characters', async ({ page }) => {
await page.goto('http://localhost:6006/?path=/story/notificationbanner--long-message');
const alert = page.getByRole('alert');
await expect(alert).toBeVisible();
const text = await alert.textContent();
expect(text!.length).toBeLessThanOrEqual(123); // 120 chars + "..."
});
Key principle: Review generated tests before running them. A passing test with a bad assertion is worse than a failing test — it gives false confidence. Verify selectors, check assertions, then add your edge cases.
You add: Coverage judgment. Does this test actually validate the requirement, or does it just pass mechanically? Is anything missing?
Start Storybook, then run the tests. You have two modes:
Interactive mode (agent + Playwright MCP) — the agent navigates to each story, interacts with the component through its accessibility tree, and reports results in chat. Good for debugging failures and exploratory testing: you can follow up conversationally ("navigate to the error state story and check if the dismiss button has an accessible name") without writing additional test code.
Scripted mode (CLI) — run npx playwright test directly from the terminal. Results are reported to the test management system automatically. Good for regression suites, CI pipelines, and any execution where repeatability matters more than interactivity.
Both modes use the same test files and both flow results to the same test management cases. Interactive mode is what you use during development when things are breaking; scripted mode is what runs in CI.
You add: Disciplined execution. Run every test case, including edge cases and error states. Don't skip the states that seem unlikely — requirements gaps often hide there.
When a test fails, the triage question is: is this a requirements gap, an implementation gap, or a test gap? The routing is different for each. See the Triage section below for the decision tree.
You add: The triage judgment. This is the QA skill that AI doesn't replace — reading a failure and understanding its root cause.
Run tests iteratively as engineering implements changes. Track which test cases are passing, which are blocked, which are failing. Use the linked backlog stories to surface test results to the PM and engineering without separate status updates. See the Test Cycle Strategies section below for how to structure your cycles.
Before sign-off, run regression coverage against areas of the codebase affected by the feature. Regressions to watch for: a design token update (color, spacing, typography), a shared component modification, a Figma redesign that triggers component regeneration, or a dependency upgrade. You don't write new tests for regression — you re-run the .spec.ts files that already exist. Those files, with their test case keys, are your regression suite.
When all acceptance criteria tests pass and regression coverage is clean, sign off on the feature for handoff. Your sign-off is the quality gate — it is not a formality. The PM and engineering proceed on the basis of your judgment that the feature meets the specified quality standard.
How to Structure Your Cycles
The test management system tracks execution history through cycles. How you structure cycles determines how useful your regression history is — whether you can answer "when did this test last pass?" and "what changed between these two sprint cycles?"
| Strategy | When to Use | How |
|---|---|---|
| One cycle per sprint | Most teams, day-to-day feature work | Create a sprint cycle at sprint start; all runs within the sprint append to it. Gives you a per-sprint pass/fail history across all cases. |
| New cycle per CI run | Release gating, production CI, environments where every run matters | Configure the Playwright reporter to create a new cycle per run. Every deployment is traceable to a specific test execution with its own timestamp. |
| Dedicated regression cycle | Scheduled nightly or weekly regression suites | A long-lived regression cycle that accumulates runs over time. Best for spotting flaky tests (alternating pass/fail across runs) and gradual degradation. |
The test management system gives you per-case history (every execution of a specific test case across every cycle), cycle comparison (what changed between two sprint cycles), and flaky test detection (a test that alternates pass/fail is visible in the run history). Choose the strategy that makes those views most useful for how your team ships.
When a Test Fails
The triage question determines who owns the fix. Three types of failures, three different routes:
The acceptance criterion is ambiguous, incomplete, or contradictory. The implementation did what was specified — but what was specified isn't actually what's needed. The fix lives in the requirements, not in the code. Route back to the PM with a specific description of the gap.
Signals: the test fails because what it's testing isn't clearly defined. Multiple valid interpretations of the acceptance criterion exist and engineering chose one that doesn't match QA's expectation.
The acceptance criterion is clear, the test is correct, and the implementation doesn't satisfy it. The code doesn't do what the requirements say it should do. Route to engineering with the specific failing test and the acceptance criterion it maps to.
Signals: the test is well-formed, the requirement is unambiguous, and the behavior is simply wrong. Engineering owns the fix.
The acceptance criterion is clear, the implementation is correct, and the test is wrong — either poorly constructed, targeting the wrong behavior, or testing a path that doesn't reflect the actual acceptance criterion. QA owns the fix.
Signals: the implementation is correct when validated manually. The test failure is a test artifact, not a product defect. Fix the test and rerun.
The agent can assist with each path. For fixing a test, describe the failure and the agent updates the selector or assertion. For filing a bug, describe the failure and the agent creates a Jira issue linked to the failing case key. For investigating a flaky test, ask the agent to navigate to the story and describe what it sees — the accessibility tree snapshot is often more informative than a failure log.
What the Harness Removes — and What Stays
| What the harness removes from QA's plate | What stays with QA |
|---|---|
| Writing test cases from scratch from requirements | Reviewing generated test cases for coverage accuracy |
| Manually copying acceptance criteria into test management | Triage judgment on every failure |
| Building coverage maps from fragmented requirements | Regression suite design and maintenance |
| Chasing PM and engineering for requirement updates | Risk-based prioritization of test execution |
| Re-linking test cases when stories change | Sign-off authority — the quality gate |
| Writing Playwright test stubs from scratch | Adding edge cases and boundary conditions the criteria missed |
| Manually posting test results to the backlog | Interpreting whether a pass/fail pattern signals a real problem |
From Acceptance Criteria to Sign-Off
Here is the complete QA flow for a single component — from test case creation through sign-off. The component is the Notification Banner with three severity variants and a dismissable option.
QA: (in coding agent) "Create test cases from the Notification Banner
acceptance criteria in docs/work/<feature>/requirements.md.
Link them to PROJ-456."
Agent: Creates PROJ-TC-201 through PROJ-TC-204 in test management.
QA didn't open the test management system.
[UX generates NotificationBanner component from Figma — includes
NotificationBanner.spec.ts with four tests tagged to the case keys]
QA: Reviews NotificationBanner.spec.ts. Selectors look correct.
Assertions match the acceptance criteria.
Adds edge case for messages longer than 120 characters (PROJ-TC-205).
Adds edge case for banner with no dismiss handler (PROJ-TC-206).
QA: "Run the NotificationBanner tests against Storybook."
Agent: (via Playwright MCP) Navigates Storybook, runs all tests.
PROJ-TC-201: Passed
PROJ-TC-202: Passed
PROJ-TC-203: Failed — dismiss button missing aria-label (no accessible name)
PROJ-TC-204: Passed
PROJ-TC-205: Passed
PROJ-TC-206: Failed — component throws when onDismiss prop is undefined
Results reported to test management automatically.
QA: "Create a bug for the missing aria-label on PROJ-TC-203,
linked to PROJ-456."
Agent: Creates PROJ-789 (bug) in backlog, linked to PROJ-456 and PROJ-TC-203.
QA: "Create a bug for the undefined onDismiss crash on PROJ-TC-206,
linked to PROJ-456."
Agent: Creates PROJ-790 (bug) in backlog, linked to PROJ-456 and PROJ-TC-206.
UX: Adds aria-label to dismiss button and guards onDismiss with
optional chaining.
QA: "Re-run the NotificationBanner tests."
Agent: All six tests pass. Results updated in test management.
QA: Marks component as QA-approved in sync-manifest.json.
All test cases green. No open bugs. Ready for sync.
Total manual test case creation: zero — agent created the base four, QA added two edge cases.
Total manual result entry: zero.
Human effort focused on: reviewing generated tests, adding edge cases, triaging the two real failures, and making the sign-off call. The mechanical work — case creation, execution, result posting — was automated. The judgment work stayed with QA.
Tips for QA in the Harness
If you can read the acceptance criteria before test cases are generated, flag ambiguous criteria early. A vague acceptance criterion produces a vague test — catching it before generation is faster than triaging a generated test that doesn't actually validate the behavior.
Generated test cases are well-structured stubs. Review them as you would a first draft — they cover the acceptance criteria, but your knowledge of the system may surface edge cases, state transitions, or interaction behaviors the criteria don't explicitly address. Add those.
Vague bug reports slow resolution. "Doesn't work" goes nowhere. "Given a banner in dismissable state, clicking the dismiss button doesn't hide the component — acceptance criterion 3 fails — implementation gap" goes straight to the right person with the right context. Invest thirty seconds in precision; it saves an hour of back-and-forth.
After each cycle, the generated and adapted test cases for the feature should be folded into the regression suite for affected areas. This is how regression coverage grows without becoming a separate maintenance burden — each cycle extends what came before.
Requirements gaps most often hide in error states, loading states, and edge cases — exactly the places QA might deprioritize under time pressure. Generated test cases may underrepresent these if the acceptance criteria don't address them. Pay extra attention to what's not explicitly covered.
In a harness where test cases are generated and validation is largely automated, the risk is that sign-off becomes a formality. It shouldn't. Your judgment is what converts green test results into a quality signal that the team can act on. That judgment — and your accountability for it — is irreplaceable.