TEST SELECTION

How to run only the tests affected by a PR

Updated July 2026 · 7 min read

Running the whole suite on every pull request is the correct answer right up until it isn't — when the suite takes 40 minutes, CI bills bite, and devs start batching changes to avoid the wait. Then you need selection: run the tests this change could actually affect. Here are the three real approaches and their honest trade-offs.

1. Dependency-graph selection (build-system level)

Tools like Nx, Turborepo, and Bazel model your workspace as a graph of packages. Change package A, and everything that imports A is "affected" — run those packages' tests, skip the rest.

2. Coverage-based selection (execution level)

Instrument a full run once, record which tests execute which lines, then map changed lines → tests that covered them. This is what Jest's --changedSince approximates and what commercial "predictive test selection" products do with ML on top.

3. Static impact analysis (artifact level)

Skip execution entirely. Read the diff, extract the concrete artifacts tests bind to — data-testid attributes, ARIA labels, element ids, route strings, visible text — and string-match them against test files. If a PR removes data-testid="checkout-submit", any spec referencing it is affected. No instrumentation, no graph, works in seconds.

Which one should you use?

Dependency graphCoverage mapStatic impact
Unit tests✅ best✅ good➖ weak
E2E / UI tests➖ blind➖ smeared✅ best
Cross-repo suites❌ no❌ no✅ yes
Setup costbuild migrationinstrumentation~zero
When signal arrivesCI timeCI timereview time

They compose: graph selection for unit tests, static impact for the E2E layer. The mistake is using only the first two and concluding E2E selection is impossible — it isn't, it just needs a different mechanism.

The review-time advantage

Approaches 1–2 answer "which tests should CI run?" Static analysis answers something better: "which tests did this PR just endanger?" — while the PR is still open. That's the difference between a faster red build and no red build: the author sees "this breaks checkout.spec.ts in the e2e repo" and fixes the spec in the same change.

This is what Testward automates as a GitHub App: anchor extraction from the diff, matching against your spec files (including across repos), an LLM pass to filter false positives, and one PR comment naming the endangered specs. You can try the extraction on any diff in your browser — no install — with the free diff scanner.

Get the affected-test list on the PR itself.

Install Testward free — the endangered specs show up as a comment before CI even starts.

Install free on GitHub