Halmurat T.
Halmurat T.

Senior SDET

Home Blog Books ask About

The Dispatch

Weekly QA notes from the trenches.

Welcome aboard!

You're on the list. Expect real-world QA insights — no fluff, no spam.

© 2026 Halmurat T.

Automation 28
  • Selenium
  • Playwright
  • Appium
  • Cypress
AI Testing 67
CI/CD 12
  • GitHub Actions
  • Slack Reporting
QA Strategy 10
Case Studies 8
Blog/AI Testing
AI TestingHalmurat T./June 25, 2026/12 min

Don't Let AI Pick Which Playwright Tests to Skip

Filed underai-testing/playwright/cicd/llm/test-generation
Don't Let AI Pick Which Playwright Tests to Skip

Table of Contents
  • Why test selection is suddenly worth the risk
  • Why does Playwright’s --only-changed miss the test that breaks?
  • The fixture-injection edge the import graph can’t see
  • What predictive test selection actually buys you
  • Where AI actually belongs: as the auditor, not the selector
  • Why an LLM selector fails silent
  • The widen-only audit prompt
  • The layered TIA pipeline I’d run in CI
  • How do you keep AI from hiding regressions in test selection?
  • The one thing to do this week

On this page

  • Why test selection is suddenly worth the risk
  • Why does Playwright’s --only-changed miss the test that breaks?
  • The fixture-injection edge the import graph can’t see
  • What predictive test selection actually buys you
  • Where AI actually belongs: as the auditor, not the selector
  • Why an LLM selector fails silent
  • The widen-only audit prompt
  • The layered TIA pipeline I’d run in CI
  • How do you keep AI from hiding regressions in test selection?
  • The one thing to do this week

Your PR changes one CSS class and CI runs all 400 Playwright specs anyway. So someone wires up --only-changed, or worse, pastes the diff into an LLM and asks “which tests should I run?” Both feel smart. Both will eventually skip the exact spec that breaks — quietly, on the change that ships to prod.

I’ve spent a decade watching enterprise suites grow past the point where running everything on every push is defensible, and watching teams reach for test selection to fix it. The selection itself isn’t the mistake. The mistake is letting a heuristic — or a language model — narrow the test set with no one checking what it dropped. AI absolutely belongs in test impact analysis. Just not in the seat everyone’s putting it in.

Why test selection is suddenly worth the risk

Running the full suite used to be the safe default because it was cheap. It isn’t anymore. The average 50-person engineering team now spends roughly $3,000–$8,000 a month just on CI/CD compute, and that’s before you count the salaries burning while people wait.

§ What full-suite-on-every-push actually costs

$3–8K/mo

CI compute

Typical 50-person team, build + test minutes

$180K/yr

Wasted salary

One team losing ~6 dev-hours/day waiting on CI, at a $150K avg salary

15–20 min

Per context switch

Recovery cost every time a dev abandons a slow pipeline

So the pressure to run fewer tests is real and it’s financial. The question is never whether to select — it’s whether your selection method fails safe (runs a test it didn’t need to) or fails silent (skips a test it did). Get that backwards and you’ve traded compute dollars for shipped regressions, which is a terrible trade for any team that’s been burned once.

Why does Playwright’s --only-changed miss the test that breaks?

Because it selects on the static import graph, and a lot of what couples a test to your app never shows up in that graph. --only-changed (shipped in Playwright 1.46, still the built-in option through 1.61) runs the spec files you touched plus any spec that imports a changed file. That catches direct import edges and nothing else.

The fixture-injection edge the import graph can’t see

Here’s where it under-selects in a real suite:

tests/fixtures/auth.fixture.ts
// You edit this fixture to change how SSO sessions are minted.
export const test = base.extend<{ authedPage: Page }>({
authedPage: async ({ page }, use) => {
await loginViaSSO(page);
await use(page);
// Specs don't `import` this by name — they get it via the
// test runner's fixture injection. The import graph can't see that edge.
},
});

A spec that uses authedPage may never statically import the fixture file — Playwright injects it. Change the fixture and the dependency-graph heuristic can wave the SSO logout spec right through. The Playwright team is explicit about this: the docs call --only-changed a heuristic that “might miss tests” and tell you to run the full suite afterward anyway. Data files loaded by path, page objects resolved by string, config-driven test data — same blind spot.

[ WARNING ]

A static selector’s failure mode is under-selection: it silently drops tests it couldn’t see were relevant. That’s the dangerous direction. The same coupling that makes shared test users break parallel execution is invisible to an import graph — runtime state, not imports.

What predictive test selection actually buys you

A correlation model fills the gap the import graph can’t. Instead of asking “what does this file import,” it asks “historically, when files like these changed, which tests actually failed?” That’s the Meta/Facebook Predictive Test Selection approach (arXiv 1810.05286), and the numbers are the reason it’s worth copying.

§ Meta's predictive test selection in production

2×

Lower test infra cost

Versus running all potentially-impacted tests

>95%

Individual failures still caught

The selection rarely drops a failing test

>99.9%

Faulty changes still reported

Almost no bad commit slips through unflagged

The model is a plain gradient-boosted decision tree trained on historical test outcomes — file paths changed, test, pass/fail — and, critically, it accounts for flakiness so a flaky red doesn’t poison the training signal. You don’t need Meta’s scale to start. A lightweight version is a table: for every CI run, log the changed paths and the specs that failed. After a few hundred runs you can rank specs by failure correlation to a given directory. That ranking is a far better selector than imports because it learns the runtime couplings the graph never sees — exactly the kind of nondeterministic failure I broke down in letting AI triage Playwright failures.

Where AI actually belongs: as the auditor, not the selector

Here’s my opinion, and it’s the whole point of this post: an LLM should never be the thing that narrows your test set. It should be the thing that catches a narrow set that’s wrong.

Why an LLM selector fails silent

Ask a model “which tests should I run for this diff?” and it will confidently return a list — including hallucinated relevance and, worse, confident omissions you can’t see. That’s under-selection with a friendly voice. But flip the job around and the model becomes genuinely useful: give it the diff, the already-selected set, and the dependency graph, and ask it to find what the selection missed.

The widen-only audit prompt

prompts/selection-audit.md
You are auditing a CI test-selection decision. Inputs:
- The git diff for this PR
- The list of specs the selector chose to run
- The repo's fixture + page-object map
Flag any changed behavior whose covering spec is NOT in the selected list.
Output only gaps. Widening the net is safe; do not propose removing tests.

The asymmetry is the safety mechanism. The model can only ever add tests back, never remove them. Its worst failure is running a spec you didn’t need — fail-safe, not fail-silent. When it spots that you edited the auth fixture but the SSO logout spec isn’t scheduled, it puts that spec back and tells you why. That’s AI doing what it’s good at — reading intent across messy context — without handing it a decision where a miss ships a bug. It’s the same line I draw with self-healing locators: assist the human, don’t replace the safety check.

The layered TIA pipeline I’d run in CI

Don’t pick one method. Stack them so each layer’s failure mode is covered by the next.

Layer 1 — Static graph (fast, cheap, under-selects)

Run npx playwright test --only-changed=origin/main on every PR. It’s free, instant, and catches the obvious import-edge cases. Treat its output as a floor, never a ceiling.

Layer 2 — Historical correlation (catches runtime coupling)

Add specs your failure-correlation table ranks high for the changed paths. This is where fixture and shared-state couplings get caught — the ones the graph is blind to.

Layer 3 — LLM audit (widen-only)

Run the selection-audit prompt. It can only add specs back. Cheap insurance against both layers above under-selecting on a change neither modeled well.

Layer 4 — Nightly full suite (the backstop)

Run everything on a schedule. This is your ground truth: every spec the PR-time selection skipped still executes within 24 hours, so a missed regression has a hard ceiling on how long it can hide.

The backstop is non-negotiable. Selection is an optimization layered on top of a full run, never a replacement for it. Skip Layer 4 and the first time your model under-selects on a Friday deploy, you find out in production.

§ Delta · PR-time Playwright run on a typical change ~6× faster feedback, regressions capped at 24h exposure

Before

400 specs, ~38 min, every push

→ ↓

After

40–70 specs, ~6 min, full suite nightly

Those numbers track with what teams report from ordinary parallelization too — a 35-minute suite cut to ~10 by running wide. The difference here is you’re cutting what runs, not just spreading it across more workers, so the savings compound with the parallel work I covered in running parallel tests without refactoring and the broader make-your-suite-faster playbook.

How do you keep AI from hiding regressions in test selection?

Measure the miss rate before you trust any layer to skip a test. For your first month, run both the selected set and the full suite on every PR, and log every case where the full suite caught a failure the selection dropped. That miss rate is the only number that tells you whether your selection fails safe.

[ TIP ]

Set a hard gate: if the selection ever misses a real failure that the nightly or shadow full-run catches, that spec’s covering paths get pinned to “always run” until you understand why the model missed it. Flaky tests already eat about 20% of CI time — don’t let a selector quietly add silent misses on top of that noise.

If you can’t measure the miss rate, you’re not doing test selection — you’re gambling with your release on the line, and calling it optimization.

The one thing to do this week

Add --only-changed=origin/main to your PR pipeline behind a full nightly run — but ship it in shadow mode first: keep running the full suite on PRs, and log every failure the selection would have skipped. After two weeks you’ll have a real miss rate, and you’ll know whether to trust selection at PR time or whether your suite’s coupling is too tangled for it yet. That measurement is worth more than any model.

Then, and only then, add the LLM as a widen-only auditor. Let it argue for more tests, never fewer. That’s the version of “AI in test selection” that makes your CI faster without making your releases a coin flip. For the rest of where I think AI does and doesn’t belong in a test suite, the AI testing pillar collects it.

[ NOTE ]

Want the battle-tested version of these calls — what to automate, what to keep human — every week? Get the newsletter: QA automation insights from 10+ years in enterprise suites, no fluff.

§ Frequently Asked FAQ
+ Is Playwright's --only-changed safe to use on its own?

Not as your only selector. It uses the static import graph, which the Playwright docs themselves call a heuristic that “might miss tests.” It can’t see fixture injection, dynamic imports, or data loaded by path, so it under-selects. Use it as a fast first layer with a full nightly suite as a backstop.

+ Can I just ask an LLM which tests to run for a diff?

No. A model asked to narrow a test set will confidently omit relevant specs you can’t audit — that’s under-selection with a friendly voice. Flip the job: give it the diff plus the already-selected set and ask only what’s missing. Constrain it to widen the set, never shrink it.

+ How is predictive test selection different from --only-changed?

--only-changed selects on static imports. Predictive test selection (Meta’s approach) trains on historical pass/fail data to learn which tests actually fail when given files change, catching the runtime couplings the import graph can’t see. In production it cut test infra cost 2× while still reporting over 99.9% of faulty changes.

+ Won't skipping tests at PR time let regressions through?

Only if you skip the backstop. Run the full suite nightly so every spec the PR-time selection skipped still executes within 24 hours. And measure your miss rate in shadow mode first — run both the selected and full sets, log every failure selection dropped — before trusting it to skip anything.

§ Further Reading 03 of 03
01AI Testing

Mocked AI Tests Pass. That's How Model Drift Ships.

Mocking the LLM keeps your Playwright suite green — and blind to model drift. Build a scheduled real-model eval gate that catches LLM drift before users do.

Read →
02AI Testing

A Correct RAG Answer Can Still Be Hallucinated

Your RAG feature returned the right answer and a green Playwright test — but nothing proved it came from what it retrieved. Here's how to test grounding.

Read →
03AI Testing

Your Grounding Tests Pass. Retrieval Recall Dropped.

You upgraded the embedding model, your RAG grounding tests stayed green, and retrieval recall quietly dropped. Here's the recall@k gate that catches it.

Read →

Don't miss a thing

Subscribe to get updates straight to your inbox.

HT

No spam · Unsubscribe anytime

Welcome aboard!

You're on the list. Expect real-world QA insights — no fluff, no spam.

§ Colophon

Halmurat T. — Senior SDET writing about test automation, CI/CD, and QA strategy from 10+ years in the enterprise trenches.

Set in
IBM Plex Sans, Lora, and IBM Plex Mono.
Built with
Astro, MDX, Tailwind CSS & Expressive Code. Served by Vercel.
Privacy
No cookies. No tracking scripts on the main thread — analytics run sandboxed via Partytown.
Source
github.com/Halmurat-Uyghur
Terminal
Try /ask to query Halmurat's notes in a shell prompt.

© 2026 Halmurat T. · Written in plain text, shipped in plain time.

Search
Esc

Search is not available in dev mode.

Run npm run build then npm run preview:local to test search locally.