← All posts
6 min read

Regression Testing: Keeping Fixed Behavior Fixed

#technology#regression-testing#software-testing#quality
📑 On this page

Fixing a defect once does not guarantee that it stays fixed.

Future refactoring, dependency upgrades, and nearby features can recreate the same conditions. Without a recorded check, the team may rediscover the defect through another user report.

A regression test preserves evidence that previously working or corrected behavior continues to work.

The best regression test captures the smallest meaningful scenario that exposed the failure.

A concrete example: leap-day billing

A subscription beginning on February 29 receives the wrong renewal date in a later year.

Before changing the implementation, a developer adds a test with:

  • the exact start date,
  • the applicable billing rule,
  • and the expected renewal date.

The test fails against the defective code, passes after the fix, and remains in the suite to protect that boundary.

What regression means

A regression is an unintended loss of previously supported behavior.

It may affect:

  • a feature that stops working,
  • a bug that returns,
  • slower performance,
  • reduced accessibility,
  • a security control,
  • or a compatibility promise.

Regression testing is broader than rerunning unit tests, though automated suites are a major tool.

Reproduce before fixing

A test that passes before the fix may not represent the defect.

The preferred sequence is:

  1. understand the failure,
  2. create a focused reproduction,
  3. observe it fail for the right reason,
  4. implement the correction,
  5. observe it pass,
  6. run broader related tests.

This proves that the change addresses the reported behavior rather than merely changing nearby code.

Choose the right level

Put the regression at the cheapest level that faithfully reproduces the risk.

  • A rounding formula belongs in a unit test.
  • A database constraint mismatch needs integration.
  • A broken account-recovery journey may deserve end-to-end coverage.
  • A layout problem may need visual or browser testing.

An unnecessarily broad browser test makes future feedback slower and less precise.

Preserve the important details

A useful regression test includes the condition that made the bug possible.

If a defect occurred only for:

  • an empty value,
  • a specific time zone,
  • simultaneous requests,
  • a Unicode filename,
  • or a permission combination,

the test must preserve that detail. A simplified "normal" example may pass without protecting the defect.

Avoid overspecializing

A test copied directly from production can include irrelevant data that hides the rule.

Reduce the reproduction until removing one more element would stop the failure. This process reveals the underlying condition and produces a readable test.

Keep identifiers and personal data synthetic.

Regression suites

Over time, individual tests form a regression suite.

The suite should represent:

  • core contracts,
  • dangerous boundaries,
  • past defects,
  • high-value workflows,
  • and compatibility expectations.

It should not become an uncurated archive where obsolete tests remain forever merely because they once existed.

Selecting tests

Fast suites may run on every change. Larger suites may run before merge, nightly, or before release.

Risk-based selection can use:

  • changed modules,
  • dependency relationships,
  • ownership,
  • historical failures,
  • and release scope.

Selection improves speed, but critical broad checks should still run often enough to catch incorrect dependency models.

Manual regression testing

Some changes require targeted manual checks:

  • complex visual behavior,
  • hardware interaction,
  • assistive technology,
  • or exploratory workflows.

A release checklist can record these checks, but repetitive stable behavior should be automated where feasible. Manual steps are slower and easier to perform inconsistently.

Performance regressions

Correct output can still become much slower or consume more memory.

Performance regression tests compare meaningful workloads against thresholds or trusted baselines. They need controlled environments because unrelated machine load can distort results.

Track trends rather than reacting to every tiny measurement variation.

Visual regressions

Screenshot comparison can reveal unintended presentation changes.

Stable visual tests control:

  • viewport,
  • fonts,
  • animations,
  • data,
  • time,
  • and rendering environment.

A human still needs to decide whether a changed image is a defect or an intended redesign.

Security regressions

When a security flaw is fixed, preserve a safe automated demonstration where possible.

For example, verify that:

  • another user's record is rejected,
  • unsafe HTML is escaped,
  • a reused token fails,
  • or excessive attempts are limited.

Do not place live secrets or weaponized production data in the suite.

Compatibility regressions

Public APIs and stored formats need tests for old consumers and data.

Useful fixtures include:

  • requests from supported client versions,
  • database records created by earlier releases,
  • old message schemas,
  • and documented error shapes.

Compatibility can break even while new feature tests pass.

False positives and false negatives

A false positive test failure reports a problem when behavior is acceptable, often because of flakiness or an obsolete expectation.

A false negative passes while the defect remains because the assertion or scenario is incomplete.

Both damage confidence. The regression must fail for the intended reason and assert the user-relevant outcome.

Bug clusters

One defect often suggests nearby cases.

A leap-day bug may lead to tests for:

  • month-end dates,
  • daylight-saving transitions,
  • different calendars,
  • and time-zone conversion.

Do not add random cases blindly. Use the discovered failure to examine the broader rule and its boundaries.

When behavior intentionally changes

A new requirement may invalidate an old regression test.

Update the test only after confirming that the contract changed intentionally. The code review should make that decision visible rather than treating the failing test as an inconvenience.

Tests protect expectations, and expectations can evolve.

Incident learning

Production incidents should improve the quality system.

Possible outcomes include:

  • a focused regression test,
  • a new monitoring alert,
  • a deployment check,
  • a runbook update,
  • or an architectural control.

Not every incident is best prevented by a unit test, but every significant incident should leave the system better prepared.

Knowledge check

  1. Why should a regression test fail before the fix?
  2. How do you choose the appropriate test level?
  3. Why reduce a production reproduction to essential details?
  4. What is a false negative in testing?
  5. Why might an intentionally changed requirement require updating a regression?

The one idea to remember

A corrected defect should leave behind focused evidence that fails for the original reason and protects the user-relevant outcome. Regression suites are maintained records of important behavior, not permanent piles of every past test.