Free QA template

Regression suite

Tests grouped by feature with a smoke tag, a fixture builder and a test for every bug fixed before.

It opens with this template loaded and runs in your browser. You don't need an account to use it; a free account saves your work and exports it.

The job it does

When a codebase keeps breaking in old places: one suite to run before every release. It comes with its own checks, so after you change it you can see at a glance that it still does the job.

What's inside

This is the template exactly as the QA Lab opens it, read-only. Open it to run it, change it and export it.

  • 3 files
  • Runs from cart.js
  • JavaScript
The brief: Regression suite: the basket

When old features keep breaking, keep one suite that runs before every release. Tests are grouped by feature in their names, the ones tagged [smoke] run on every deploy, every fixed bug gets a [bug #id] test so it stays fixed, and fixtures.js builds the test data so each test says only what matters to it.

Put your own module in place of cart.js and grow the suite one bug at a time.

Done when
  • All my tests pass
  • total({"lines": [{"sku": "tea", "priceCents":…) returns 1097
  • No uncaught errors
cart.js
// The code under test: Mangrove Market's basket.
export function addItem(cart, item, qty = 1) {
  if (!Number.isInteger(qty) || qty < 1) throw new Error('qty must be a whole number of at least 1');
  const lines = cart.lines.map((l) => ({ ...l }));
  const line = lines.find((l) => l.sku === item.sku);
  if (line) line.qty += qty; else lines.push({ sku: item.sku, priceCents: item.priceCents, qty });
  return { ...cart, lines };
}

export function removeItem(cart, sku) {
  return { ...cart, lines: cart.lines.filter((l) => l.sku !== sku) };
}

export function total(cart) {
  const sum = cart.lines.reduce((s, l) => s + l.qty * l.priceCents, 0);
  const off = cart.coupon ? Math.min(sum, cart.coupon.offCents) : 0;
  return sum - off;
}
fixtures.js
// Test data builders: each test says only what matters to it.
export const tea = { sku: 'tea', priceCents: 399 };
export const rice = { sku: 'rice-5kg', priceCents: 1250 };

export function aCart(overrides = {}) {
  return { lines: [], coupon: null, ...overrides };
}
cart.test.js
import { addItem, removeItem, total } from './cart';
import { aCart, tea, rice } from './fixtures';

// Tags in the name: [smoke] runs on every deploy; [bug #id] keeps a fixed bug fixed.
// Group by feature with the name prefix, so a failing run reads like a list of broken features.

test('[smoke] basket › adding an item shows it with its price', () => {
  expect(addItem(aCart(), tea).lines).toEqual([{ sku: 'tea', priceCents: 399, qty: 1 }]);
});
test('[smoke] basket › the total adds every line', () => {
  expect(total(addItem(addItem(aCart(), tea, 2), rice))).toBe(2048);
});
test('basket › adding the same item again raises its quantity', () => {
  expect(addItem(addItem(aCart(), tea), tea, 2).lines[0].qty).toBe(3);
});
test('basket › removing an item removes the whole line', () => {
  expect(removeItem(addItem(aCart(), tea), 'tea').lines).toEqual([]);
});
test('basket › adding never changes the basket it was given', () => {
  const before = addItem(aCart(), tea);
  addItem(before, tea);
  expect(before.lines[0].qty).toBe(1);
});
test('basket › a quantity of 0 is refused', () => {
  expect(() => addItem(aCart(), tea, 0)).toThrow('at least 1');
});
test('[bug #212] coupons › a coupon bigger than the basket makes it free, not negative', () => {
  expect(total(aCart({ lines: [{ sku: 'tea', priceCents: 399, qty: 1 }], coupon: { offCents: 500 } }))).toBe(0);
});
test('[bug #187] coupons › an empty basket with a coupon costs 0', () => {
  expect(total(aCart({ coupon: { offCents: 500 } }))).toBe(0);
});

The lesson behind it

Learn why it works, with a podcast and a quiz for each lesson.

  • Bug-report template

    A bug report as data (steps, expected, actual, severity) with a failing test that reproduces it.

  • Test plan

    Scope, risks, environments and entry/exit criteria as data, with checks that every risk has tests.

All QA templates · Every template