BXUP Track progress & test yourself — free
QA & Testing · Module · ~9 min read
QA & TESTING · MODULE

AI-Assisted Automation Engineering

Agentic IDEs write Playwright suites that compile, run and pass — and passing is exactly the problem. This module teaches spec-first authoring under team conventions, API suites from OpenAPI, ARIA-snapshot assertions, and the anti-pattern catalog for AI-generated tests, with mutation testing as the tiebreaker that proves your assertions actually assert something.

The tooling context matters: Playwright, Selenium and Cypress appear in roughly 78% of QA postings, and AI coding assistants — Claude Code, Cursor, GitHub Copilot — are now the default way test code gets written in product companies. But there is a documented catch. Research on LLM-generated tests (arXiv 2601.08998) finds them measurably more flaky than human-written ones, and Stack Overflow 2025 has 66% of developers frustrated by AI code that is almost right. Almost-right application code fails visibly. Almost-right test code passes silently — which is why this module treats assertion strength, not generation speed, as the deliverable.

The scenario — a green suite that catches nothing

  1. MONDAY

    Ananya — SDET, six years, at a Bengaluru D2C commerce company — inherits checkout coverage for the new promotions engine. She points Cursor at the feature: "Write Playwright tests for the coupon flow." Twenty minutes later: 38 tests, all green. She merges and moves on.

  2. THURSDAY

    A developer PR breaks stacked-coupon math — two discounts now apply where policy allows one. The suite stays green. The bug ships to staging and is caught by a support escalation from UAT, not by automation.

  3. THE POST-MORTEM

    Ananya reads the generated suite properly for the first time. await page.waitForTimeout(3000) before every assertion. Tests that assert the coupon input field exists rather than that the discount math is correct. One test literally asserts the response equals whatever the response was — captured at generation time from the buggy build. Three tests depend on execution order.

  4. FRIDAY

    She runs Stryker mutation testing against the suite. Mutation score: 31% — two-thirds of deliberate code breakages survive her tests. The suite was not thin; it was decorative.

  5. TWO SPRINTS LATER

    Same feature, new discipline: a spec-first prompt with the team's conventions file loaded, a review pass against the anti-pattern rubric, ARIA-snapshot assertions instead of brittle selectors, and a mutation gate in CI. Mutation score: 84%. The next promotions bug is caught by the suite, in the PR, before merge.

Nothing about Ananya's Thursday was unusual. Generated tests optimize for plausibility — they look like tests, run like tests, and report like tests. Whether they can fail when the product breaks is a property you have to engineer in, and this module is that engineering.

What You'll Learn

  • Spec-first prompting in agentic IDEsdrive Claude Code, Cursor or Copilot from a written test specification with team conventions loaded as rules files, so generated code lands in your architecture, not the model's habits (UC-09).
  • Test generation with a mutation gatepoint a coding agent at untested code for unit and integration coverage, then prove assertion strength with Stryker or mutmut before the coverage number is allowed to mean anything (UC-58).
  • API suites from OpenAPIgenerate happy-path, auth, negative and contract tests from the schema, then attack your own suite to find what it misses (UC-14).
  • ARIA-snapshot assertionsthe accessibility-tree assertion style that survives DOM regeneration, replacing brittle CSS/XPath in the AI era (UC-15).
  • The anti-pattern catalogthe recurring defects of AI-generated test code, and the review clinic that removes them (UC-16).
  • Fixtures, harnesses and legacy migrationconvention-grounded scaffolding of auth states, seeding and stubs, plus agentic Selenium-to-Playwright migration with behavior-parity checks (UC-17, UC-13).

Spec-first, conventions-loaded — how professionals prompt for test code

"Write tests for the coupon flow" delegates the two decisions that were your job: what to test and how your team writes tests. The professional pattern inverts this. You write a short test specification — scenarios, boundaries, the assertions that matter, in plain language — and the agent turns spec into code under your conventions. The conventions travel in a rules file (CLAUDE.md, .cursorrules, Copilot instructions) committed to the repo:

  • Architecture rulespage objects or locator helpers, fixture usage, where test data comes from, what gets mocked and what runs real.
  • Assertion rulesweb-first assertions only (await expect(locator).toHaveText(...)), no waitForTimeout, every test asserts an outcome the user cares about, not an implementation detail.
  • Naming and structure rulesfile layout, test titles that read as behavior, tagging conventions for smoke/regression subsets.
  • Forbidden-pattern rulesthe anti-pattern catalog below, stated as prohibitions the agent must not emit; agents follow negative rules well when the rules are explicit and in context.

The payoff compounds: with conventions in context, review shifts from "rewrite this to match our style" to "is this assertion strong enough?" — which is the review that matters. Ananya's spec for the rewrite was eleven lines; the agent produced code she could review in one pass because it was shaped like her team's code.

Note

Rules files are shared team infrastructure, not personal settings. Treat them like lint config — versioned, reviewed, and improved every time a review catches the agent doing something the rules should have prevented.

The anti-pattern catalog — what AI-generated test code gets wrong

These five patterns account for most of the gap between "suite is green" and "suite protects the product." Each is common in generated code because each is common in the public code the models learned from:

Anti-patternWhat it looks likeWhy generation produces itThe fix
Sleep-based waitswaitForTimeout(3000) before actionsTimeouts "work" in demos and dominate training dataWeb-first assertions that auto-retry until the condition holds
Tautological assertsAssert element exists; assert response equals captured responseExistence is the easiest postcondition to infer from a DOMAssert the business outcome: the math, the state change, the message
Over-mockingMock so much that the test exercises the mockMocks make generated tests pass reliablyMock at system boundaries only; keep one integration path real
Order dependenceTest B needs the cart state test A createdGenerated tests share setup implicitlyIndependent fixtures per test; run the suite shuffled in CI
Selector brittlenessDeep CSS chains, positional XPathModels mimic recorded-selector styleRole-based locators and ARIA snapshots (next section)

The review clinic is a fifteen-minute pass with this table as the rubric — and mutation testing is the tiebreaker when reviewers disagree about whether an assertion is strong enough. Mutation tools (Stryker for JS/TS, mutmut for Python) plant small deliberate bugs — flip a comparison, delete a statement — and rerun the suite. Every mutant that survives is a bug class your tests would miss. Coverage tells you code was executed; mutation score tells you code was checked. For AI-generated suites the distinction is the whole game, because generated tests are systematically strong on execution and weak on checking.

Exam Tip

Shown a generated test and asked what is wrong with it, look for the assertion first. "The test asserts the element is visible but the requirement is about the computed total" is the expected shape of answer — tautological and outcome-free assertions are the most-planted defect in this domain's items.

ARIA snapshots — assertions built for regenerated DOMs

When AI tools regenerate frontend code freely, the DOM becomes a moving target and CSS/XPath assertions become maintenance debt. Playwright's ARIA snapshots assert against the accessibility tree — the semantic structure of roles, names and states that assistive technology sees:

await expect(page.locator('.checkout-summary')).toMatchAriaSnapshot(`
  - heading "Order summary" [level=2]
  - list:
    - listitem: /Espresso Grinder .* ₹12,499/
    - listitem: /Coupon FESTIVE10 .* −₹1,250/
  - button "Place order"
`);

Three properties make this the AI-era default. It is resilient: a refactor that changes divs and classes but preserves semantics passes, while a change that breaks what users perceive fails. It is readable: the assertion is a human-legible statement of what the page should be, reviewable by someone who has never seen the implementation. And it double-covers: a page whose accessibility tree is assertable is a page with an accessibility tree — regressions in semantic structure fail functional tests. The discipline it demands: snapshot the regions that carry the requirement, not whole pages, and review snapshot updates like code — an approved-but-wrong snapshot update is the visual-baseline problem all over again.

API suites from the schema — then attack your own work

API testing is the strongest generation story in this module because the ground truth is machine-readable: an OpenAPI or GraphQL schema declares endpoints, types, auth and status codes, so the model is grounded rather than guessing. The workflow:

  1. Generate from the spec. Happy paths per endpoint, auth matrix (no token, expired token, wrong scope), negative cases per constraint, and contract assertions on response shape.
  2. Attack your own suite. Before trusting it, ask: which bugs would this miss? Wrong-but-valid status codes (200 where 201 belongs), extra undocumented fields, missing auth checks on one verb, contract drift in a nested object. Add property-level Schemathesis fuzzing for what example-based generation never reaches.
  3. Strengthen and regenerate. Feed the misses back as explicit requirements; keep the strengthened suite, not the first draft.

Alongside the suites, the same convention-grounded generation scaffolds the boring 60% of framework ownership — auth-state fixtures, data seeding, MSW/WireMock network stubs, custom matchers — with one rule: you must be able to explain every generated line of harness code, because harness magic is where debugging goes to die. And for legacy estates, agentic migration (Selenium/Java to Playwright/TypeScript) is now a realistic engagement — with behavior parity as the verification spine: old and new suites run against the same build, and every converted spec must catch the same planted bugs the original caught, before the original is deleted (UC-13).

CI GATE · PR #482

promotions-suite → mutation report

84%MUTATION SCORE — threshold 75%, gate passed217 mutants generated · 182 killed · 35 survived
  • Killed: comparison flips in discount math — stacked-coupon asserts hold
  • Killed: statement deletion in coupon-expiry check
  • Survived: 35 mutants in logging and error-copy paths — triaged as accepted, documented in mutation-allowlist.md
  • Gate policy: score below threshold blocks merge; allowlist changes require test-lead review

Coverage says the code ran. This number says the tests were watching.

Where this lands in your week

  • In feature workspec-first prompts with the rules file loaded; the agent writes, you review against the anti-pattern rubric, and review time drops because the code arrives in your architecture.
  • In PR reviewreviewing AI-generated test code (yours and developers') against the catalog becomes a named QA responsibility; mutation score settles arguments evidence-free review cannot.
  • In suite maintenancenew UI assertions default to ARIA snapshots; each brittle-selector fix migrates that test rather than patching the selector.
  • In the backloguntested legacy modules become agent-plus-mutation-gate tasks: an afternoon each, instead of the sprint each that kept them untested forever.
Key Takeaway:

AI makes test code cheap and assertion strength expensive — the suite that matters is the one that fails when the product breaks. Prompt spec-first under versioned conventions, review against the anti-pattern catalog, assert on ARIA semantics and business outcomes, and let mutation testing — not the green check — tell you whether your tests are watching.

Try it now

  1. Mutation-test one suite. Run Stryker or mutmut against your most-trusted test file. Triage five surviving mutants: real assertion gap or acceptable? Fix the two worst.
  2. Write a rules file. Draft ten test-code conventions for your repo — architecture, assertions, forbidden patterns — commit as CLAUDE.md or .cursorrules, and generate one test with and without it loaded. Diff the results.
  3. Attack a generated API suite. Generate tests from one OpenAPI endpoint's spec, then list three bugs the suite would miss and add the assertions that catch them.

Take this into Lab 04 (AI-authored suite quality clinic) — planted anti-patterns, mutation scores before and after — and Lab 06 (API suite from OpenAPI with an assertion audit) against a server with seeded contract bugs. Companion playbooks: pb-08 through pb-14.

This is the free reading view. Open BXUP to track your progress, run the hands-on labs, and prove it with original, exam-pattern assessments.
© Anvi Innovate · BXUP — Be Exponentially Upskilled · BXUP is an independent learning platform, not affiliated with or endorsed by AWS, Microsoft, Google, NVIDIA, IBM, Salesforce, Databricks, Oracle or Anthropic. All trademarks belong to their respective owners. · bxup.in