Software Development

What Is Regression Testing and How Do You Do It?

What regression testing is, how to choose what to retest, and how to automate it so new releases stop breaking features that used to work.

Quick answer

Regression testing means re-running tests after a code change to make sure features that already worked still work. Teams do it by keeping a suite of automated tests for important behavior, running a fast subset on every change and the full suite before release, and adding a new test every time a bug is fixed so it can't come back.

What Is Regression Testing and How Do You Do It?

Photo: Unsplash

On this page

A customer emails to say checkout is broken. Nobody touched checkout. The team only changed the discount code feature. But the discount change altered a shared pricing function, and now orders with gift cards fail.

That’s a regression: something that used to work and stopped working because of a change somewhere else. Regression testing is how teams catch these problems before customers do. This guide explains what regression testing is, how to decide what to retest, and how to automate it so releases stop breaking old features.

What regression testing means

Regression testing is re-running existing tests after a change to confirm that the change didn’t break anything that already worked. The change could be a new feature, a bug fix, a refactor, a library upgrade, a configuration change or new infrastructure.

It’s different from the testing you do on the change itself:

  • Testing the new feature asks: “Does the new thing work?”
  • Confirmation testing (also called retesting) asks: “Is the bug we fixed actually fixed?”
  • Regression testing asks: “Did anything else break along the way?”

Regressions happen because software is connected. Shared functions, databases, APIs, styles and third-party libraries mean a change in one place can ripple out. The bigger and older the codebase, the harder it is for any one person to predict those ripples.

Why releases keep breaking old features

If your team keeps shipping bugs into features nobody touched, the usual causes are:

  • No automated tests for existing behavior. Each release depends on someone remembering to click through everything.
  • Tests that exist but don’t run. They live in the repository but aren’t part of the build pipeline.
  • Manual regression that’s too slow. A full manual pass takes days, so it gets cut short when deadlines hit.
  • Flaky tests. Tests that sometimes fail for no real reason train the team to ignore failures.
  • Dependency updates without testing. A library upgrade changes behavior in ways the release notes didn’t mention.
  • Faster code changes. AI coding assistants and large refactors can touch many files at once, which raises the chance of side effects.

Regression testing fixes these by making “check the old stuff still works” automatic and routine.

Types of regression testing

Type What it covers When to use it
Full regression The entire test suite Before major releases, after big refactors or platform upgrades
Selective (partial) regression Tests related to the changed area plus critical paths Most day-to-day changes
Risk-based regression Tests for the highest-risk and highest-value features When time is short or the suite is large
Smoke test A small set of checks that the app starts and core flows work After every deployment, before deeper testing
Visual regression Screenshot comparisons to catch layout or styling changes Front-end changes, design system updates
Performance regression Response times and resource use compared with a baseline Changes to queries, caching or infrastructure (see load testing)

Most teams combine these: a smoke test and selective regression on every change, and full regression before release.

Key takeaway: Every bug you fix should leave behind a test. Over time, that habit turns your regression suite into a record of everything that has ever broken, and stops it breaking again.

How to choose what to retest

You can’t test everything all the time, so scope selection matters. Use these questions to decide what goes into each run:

  1. What changed? Start with tests for the modified code and anything that calls it.
  2. What depends on it? Shared libraries, database tables, APIs and design components affect many features.
  3. What would hurt most if it broke? Payments, sign-in, sign-up, data saving and anything legally or financially sensitive belong in every run.
  4. What has broken before? Areas with a history of bugs deserve permanent coverage.
  5. What do customers use most? Analytics show which flows matter to real users.

Some tools automate part of this. Microsoft’s Test Impact Analysis in Azure Pipelines, for example, selects the tests affected by a commit, plus previously failing and newly added tests, and falls back to running everything when it can’t tell what changed. Test frameworks also help you organize tests into groups. In pytest, for instance, you can mark tests and run subsets, such as pytest -m "not slow" for a quick run.

Automating regression tests

Manual regression doesn’t scale. Each release adds features to check, while the time available stays the same. Automation is what makes regular regression testing realistic.

Build the suite in layers. Most regression coverage should come from fast unit and API tests, with a smaller number of end-to-end tests for critical user journeys. Our guide to unit vs integration vs end-to-end testing explains how to balance them.

Run it in your pipeline. Connect tests to your CI/CD pipeline so they run on every pull request. On GitHub, branch protection can require status checks to pass before changes are merged, which stops a failing regression suite from being ignored.

Split fast and slow runs.

Run Contents Target time Trigger
Pull request Unit tests, API tests, smoke tests for changed areas Minutes Every change
Main branch Broader integration and end-to-end tests Under an hour Every merge
Nightly or pre-release Full suite, visual and performance checks, all browsers and devices Hours if needed Schedule or release candidate

Add visual checks for front ends. Screenshot comparison tools catch layout changes unit tests miss. Playwright’s visual comparisons, for example, store a reference screenshot and compare later runs against it. Its documentation warns that rendering varies by operating system, browser and hardware, so generate baselines in the same environment where tests run.

Keep a manual layer. Automation checks what it’s told to check. Short exploratory sessions on risky changes still find surprises. See manual vs automated testing for where each fits.

Keeping the regression suite healthy

A regression suite is code, and it needs maintenance.

  • Fix or quarantine flaky tests quickly. A test that fails randomly destroys trust in every other result. Track flaky tests, move them out of the blocking run and fix the cause.
  • Delete tests for removed features. Old tests slow every run and confuse new team members.
  • Watch run time. If the pull request run creeps past 10 to 15 minutes, developers start working around it. Parallelize or move slower tests to later stages.
  • Use stable test data. Create test data in each test or reset it between runs, so tests don’t depend on each other.
  • Review coverage of critical flows. Coverage percentages are a rough guide. What matters is that your most important user journeys are tested.

Where to start: a 6-step plan

  1. List your top 10 user journeys. Sign-up, login, search, checkout, key forms, reports. Ask support which ones generate the most complaints.
  2. Automate a smoke test for each. Even a simple check that each journey completes catches a lot.
  3. Run tests on every pull request. Make passing tests a requirement for merging. Our guide to building a CI/CD pipeline shows how.
  4. Adopt the “bug, then test” rule. Every bug fix includes a test that would have caught it. Test-driven development makes this natural.
  5. Schedule a full run before releases. Include browsers, devices and integrations you support.
  6. Review monthly. Remove dead tests, fix flaky ones and add coverage where bugs escaped to production.

Pair this with a pre-launch QA checklist for release day and move checks earlier with shift-left testing.

Conclusion

Regression testing is the safety net that lets teams change software without breaking what already works. Choose what to retest based on what changed, what depends on it and what matters most to customers. Automate the bulk of it in layers, run a fast subset on every change and the full suite before release, and add a test for every bug you fix. Keep the suite fast and trustworthy, and releases stop being a gamble.

Sources

Questions readers ask

Frequently asked questions

What is regression testing in simple terms?

Regression testing is checking that things that used to work still work after you change the software. You re-run existing tests after a new feature, bug fix, upgrade or configuration change. If a test that used to pass now fails, the change has caused a regression, and you fix it before release.

What is the difference between regression testing and retesting?

Retesting, or confirmation testing, checks that a specific bug you fixed is actually fixed. Regression testing checks that the fix, or any other change, didn't break something else. You usually do both: retest the fixed bug, then run regression tests on related areas and critical user journeys.

How often should you run regression tests?

Run a fast, automated subset on every code change, ideally on every pull request. Run broader suites when code merges to the main branch, and the full regression suite before each release. Teams that deploy several times a day rely almost entirely on automated regression tests in their CI/CD pipeline.

Can regression testing be fully automated?

Most of it can and should be. Unit, API, end-to-end and visual regression checks automate well and run quickly. Keep a small manual layer for exploratory testing of risky changes, usability and visual judgment, because automated tests only check what they were written to check. Teams usually aim for automation as the main safety net.

What tools are used for regression testing?

Teams use the same test frameworks they use for other automated testing: unit test tools like JUnit, pytest or Jest, API testing tools, and browser automation tools such as Playwright, Cypress or Selenium. CI/CD platforms such as GitHub Actions, GitLab CI or Jenkins run the tests automatically on each change.

How do you select test cases for regression testing?

Start with tests covering the code that changed and anything that depends on it. Add tests for your most critical and most-used features, such as login and payments, and for areas with a history of bugs. Some tools use test impact analysis to pick affected tests automatically. Run the full suite before major releases.

Why do regression tests fail randomly?

Random failures usually come from flaky tests, not real bugs. Common causes are timing issues, shared test data, dependence on test order, unstable test environments and external services. Flaky tests erode trust in the whole suite, so track them, move them out of blocking runs and fix the underlying cause quickly.

Reader reviews

Was this guide useful

No reviews yet. Share your experience and help other readers.

Write a review
Your rating
Never shown publicly

Reviews are checked before they appear. We never show your email. Please review only places or services you have used.

Manishdai
Written by

Manishdai

Manishdai writes about the technology that is reshaping every industry — from AI agents and cloud platforms to healthtech, fintech and the IT companies building it all across the United States.