Skip to content

Regression Testing

A regression test verifies that behaviour which used to work still works after a change. Every git push, dependency bump, refactor or config tweak risks breaking something unrelated — regression testing is the net that catches it before users do.

before ──► change ──► regression suite ──► behaved as before?
│ pass │
└ fail → a regression └ ship with confidence

Regression testing is not a test level (unit, integration, E2E) but a purpose: any test at any level can be a regression test. The practice is usually automated and lives in CI, growing over time as each fixed bug earns a permanent test.

Use it for

  • After every code change, before merge or release
  • After upgrading a dependency, framework or runtime
  • Whenever a bug is fixed — add a test so it can never regress silently
  • Refactors that should preserve observable behaviour

Avoid it when

  • You are verifying one specific fix in isolation → a sanity test is cheaper and sharper
  • You need to confirm the build even boots → start with a smoke test
  • The “test” only re-asserts the implementation details of the code you just wrote
Tool Ecosystem Notes
Vitest / Jest JS/TS Snapshot tests catch unintended output drift
Playwright Multi Replay critical journeys on every build
pytest Python Parametrised regression cases; pytest-regressions
Go testing Go go test ./...; golden files for output comparison
JUnit 5 Java/JVM Suites + tags; run the full suite on every PR
xUnit / NUnit .NET dotnet test across the whole solution
Robot Framework Python Keyword suites run on every release candidate
BackstopJS / Percy Multi Visual regression (screenshot diffing)
ApprovalTests Multi Golden-master / approval testing
k6 Multi Performance regression baselines
Terminal window
npm install -D vitest @vitest/coverage-v8
npx vitest run --coverage
import { describe, it, expect } from 'vitest';
import { formatInvoice } from './invoice';
describe('formatInvoice (regression)', () => {
it('keeps the established output format', () => {
expect(formatInvoice({ total: 1200, currency: 'USD' }))
.toMatchInlineSnapshot('"$12.00"');
});
});
  • Add a test with every bug fix. A fixed bug without a regression test will come back.
  • Prefer behaviour over snapshots alone. Snapshots catch drift but say nothing about intent; pair them with explicit asserts.
  • Keep the suite fast enough to run every time. If it is too slow to run, it will not run.
  • Do not assert implementation details. Tests bound to private structure fail on harmless refactors.
  • Update goldens deliberately. A golden change should be a reviewed, intended change, never a blind regenerate.
  • Quarantine, do not ignore, flaky tests. A red suite people ignore is not a safety net.

Self-assessment quiz

Pick one answer per question, then press Check answers.

  1. What is the core purpose of regression testing?
  2. A bug is fixed and merged. What should accompany the fix?
  3. Which statement about regression testing is true?
  4. Why should a golden/snapshot file never be regenerated blindly?
  5. A test suite is so slow that it only runs nightly. What is the risk?