The Role Workflow Test Cycles Triage What Changes Example Tips
Roles / QA Engineer

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

01
Agent Creates Test Cases

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.

Example Prompt
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.

02
Review Generated Test Stubs

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:

Generated Test Stub — Example
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 You Add
// 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?

03
Run Against Storybook

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.

04
Triage Failures

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.

05
Manage Test Cycles

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.

06
Run Regression Suites

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.

07
Sign Off

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:

01
Requirements gap → Route to PM

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.

02
Implementation gap → Route to Engineering

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.

03
Test gap → QA fixes the test

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.

Full Flow (Illustrative)
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

01
Engage with requirements before test case generation

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.

02
Treat test stubs as starting points, not finished artifacts

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.

03
Be precise when routing failures

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.

04
Build regression coverage from the current cycle's tests

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.

05
Don't skip error states and edge cases

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.

06
Your sign-off is the quality gate — treat it as one

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.