How to write regression tests so bugs never come back
regression testing, test coverage for bug fixes, commit-linked tests, test naming conventions, prevention vs detection
Regression Tests Are Bug Insurance
Every bug you fix without a test will come back. Code changes, refactors, and new features all reintroduce old bugs when no automated check prevents them. A regression test is the permanent record that a specific bug was found, fixed, and must never recur.
Naming and Linking
Name regression tests after the bug or ticket they guard against. This creates a searchable history and documents why the test exists.
// Jest example -- test names reference the bug context
describe('applyDiscount', () => {
// Bug BUG-147: coupon sent as string caused string concatenation
it('BUG-147: handles string coupon value correctly', () => {
expect(applyDiscount(100, '20')).toBe(80);
expect(applyDiscount(100, '0')).toBe(100);
expect(applyDiscount(50, '50')).toBe(0);
});
// Bug BUG-203: negative coupon values increased price
it('BUG-203: rejects negative coupon values', () => {
expect(() => applyDiscount(100, -10)).toThrow('Invalid coupon');
});
});
Coverage of the Fault
Regression tests cover the specific input that caused the bug and its near-neighbors (empty value, zero, boundary cases around the fault). You are not trying to test every possible input -- you are permanently capturing the exact condition that broke the system. Add these tests to your CI pipeline so they run on every commit. A failing regression test in CI is a high-priority alert.
