What Is Regression Testing? Techniques + a Reusable Checklist

Regression testing explained: what it is, risk-based selection, smoke vs regression, a prioritized checklist you can reuse, and how to keep the suite fast.

Regression testing answers one question after every change: did anything that used to work still work? New features get the attention, demos, and test plans — but the bugs that burn teams are almost always in code nobody touched. The ISTQB defines regression testing as "a type of change-related testing to detect whether defects have been introduced or uncovered in unchanged areas of the software" (see the ISTQB Glossary entry). The phrase "unchanged areas" is the part teams get wrong: you are not retesting the change, you are testing everything the change could have broken around it.

Why regressions happen (and why re-running everything is not the answer)

A regression sneaks in through the seams between modules. Typical mechanisms:

  • Shared code changes. A utility function gets a "safe" tweak; three callers downstream depended on the old edge-case behavior.
  • Refactors with green unit tests. Unit mocks encode the old assumptions, so a broken integration still passes every unit suite.
  • Config, dependency, and data drift. The code is identical but the library version, migration, or feature flag underneath it moved.
  • Fixed bugs that were never folded back into the suite. The bug returns because no test ever existed that would have caught it.

The instinctive answer — re-run the entire suite on every commit — fails economically long before it fails technically. A 4,000-case suite at 30 seconds per case is 33 hours of wall-clock time per pass. By the time the pass finishes, the code has moved again. Practical regression testing is therefore a selection problem: run the right subset, fast, on every change.

Choosing what to run: risk-based selection

Rank every candidate case on two axes — the likelihood the change broke it, and the impact if it silently broke. Then apply a simple selection order:

  • All cases touching changed modules — including their neighbors at integration boundaries, not just the changed functions.
  • All cases for bug fixes shipped in this release. A fixed bug without a regression case is a timed reinstall: fold every fix into the suite permanently.
  • High-traffic, revenue-adjacent flows (login, checkout, signup, search) even when nothing near them changed — these are the failures users find first.
  • Historically flaky or defect-dense areas. Modules that produced bugs last quarter statistically produce them again.

Everything else runs on a rotation — nightly, weekly, or before release only. That rotation is what keeps daily passes inside a coffee break instead of a day.

Smoke vs sanity vs regression: the layer cake

The three terms blur together because they are layers of the same pyramid, distinguished by breadth and timing rather than technique:

LayerQuestion it answersBreadthWhen it runs
SmokeIs the build even testable?A handful of critical-path cases (app loads, login works, core API responds)First minutes after every build/deploy — a broken smoke aborts further testing
SanityDoes the changed area behave?Narrow, unscripted checks around the specific changeAfter a minor fix, instead of a full pass
RegressionDid the change break anything else?The selected (or full) existing suitePer merge to main, nightly, and before every release

A useful rule of thumb: smoke is a gate, sanity is a spot-check, regression is an insurance policy. If your smoke suite fails, skip the regression pass — you will only collect noise.

A regression checklist you can reuse

Copy this into your release process. It is ordered — a failure at the top changes what you do at the bottom:

  1. Smoke first. 5–10 critical-path cases. If these fail, stop and fix the build; a regression pass on a broken build measures nothing.
  2. Changed-module cases. Every case whose steps touch a file, endpoint, or screen in the diff — plus one integration case per boundary.
  3. Fix-verification cases. Every bug fixed in this release has a case that reproduces the original bug, and it passes.
  4. Core-flow cases. Login/checkout/search/upload, regardless of the diff.
  5. Data-boundary cases. Empty inputs, maximum lengths, special characters — the class of bugs that survives "it worked in dev".
  6. Cross-browser/device sample. At minimum one pass on the second most popular browser your analytics show, not just the one developers use.
  7. Visual spot-check. Layout breaks (a missing CSS file, a broken bundle) survive functional green lights; look at one page per template.
  8. Log results per case, including passes. "Regression passed" as a single checkbox hides which cases were skipped.

Working regression checks into the broader process

Regression cases are written once and executed hundreds of times, so their quality bar is higher than one-off test cases: exact test data, no dependence on execution order, and self-contained teardown. The structure follows the same anatomy as any good case — if your team is still standardizing case writing, start with our guide on how to write test cases, then convert the review comments you get into permanent suite rules. When a regression pass finds a defect, the report needs the same reproducibility discipline — our bug report template covers the severity/symptom separation that keeps triage fast.

Metrics close the loop. Track two numbers per pass: the percentage of the planned suite actually executed (execution rate) and the defect removal efficiency of the release. If execution rate keeps dropping below ~80%, the suite is too big for its window — prune or parallelize instead of silently skipping. The QA Metrics Calculator computes both, plus defect density per module, which tells you where the next regression is most likely to come from.

Where standards fit

If your organization needs a formal reference — for audits, certifications, or process documentation — the international standard for software testing is the ISO/IEC/IEEE 29119 series, whose first part defines the core concepts and vocabulary (ISO/IEC/IEEE 29119-1:2022). It formalizes exactly the layered structure above: test levels, test types, and regression as change-related testing. You do not need the standard to test well, but citing it ends "is this the right process?" arguments faster than any blog post — including this one.

Related reading