Free QA template

Bug-report template

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

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 you find a bug: a report a developer can act on at once, with the test that proves it is fixed. 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 bug.js
  • JavaScript
The brief: Bug report: BUG-342

When you find a bug, write a report a developer can act on at once (steps, expected, actual, environment, severity) and a test that reproduces it. The knownBug test passes while the bug is there and fails the moment it is fixed, which tells whoever fixes it to make it a normal test.

Try it: fix isCodeValid in codes.js (the last day should count until midnight at its end), run, and follow what the failing test says.

Done when
  • All my tests pass
  • No uncaught errors
bug.js
// A bug report as data: a developer can act on it at once, and the test below reproduces it.
export const BUG = {
  id: 'BUG-342',
  title: 'Discount code rejected on its last day',
  severity: 2, // 1 blocks everyone · 2 a main flow is wrong · 3 a workaround exists · 4 cosmetic
  environment: 'app 4.12 (Android), staging, 2026-03-31 10:15 store time',
  steps: [
    'Create code SPRING10, valid until 2026-03-31',
    'On 2026-03-31 at 10:15, add an item and enter SPRING10',
  ],
  expected: 'The code is accepted all day on 31 March',
  actual: 'The app says "This code has expired"',
  notes: 'Expiry dates are compared as midnight at the start of the day, so the last day never counts.',
};
codes.js
// The code with the bug (the fix goes here, and then the known-bug test must become a normal test).
export function isCodeValid(code, now) {
  // BUG-342: validUntil is a date, so it means midnight at the start of that day
  return now <= new Date(code.validUntil + 'T00:00:00');
}
bug.test.js
import { BUG } from './bug';
import { isCodeValid } from './codes';

// knownBug: passes while the bug is still there, and fails as soon as it is fixed, telling you to
// turn it into a normal test (the same idea as an "expected failure" in other test tools).
function knownBug(id, name, fn) {
  test(id + ' (known bug) › ' + name, () => {
    let failed = false;
    try { fn(); } catch (e) { failed = true; }
    if (!failed) throw new Error(id + ' looks fixed: make this a normal test and close the bug.');
  });
}

const spring = { code: 'SPRING10', validUntil: '2026-03-31' };

test('the report is complete', () => {
  expect(Boolean(BUG.title && BUG.environment && BUG.steps.length && BUG.expected && BUG.actual && BUG.expected !== BUG.actual)).toBe(true);
  expect([1, 2, 3, 4]).toContain(BUG.severity);
});
test('codes › a code works before its last day', () => {
  expect(isCodeValid(spring, new Date('2026-03-30T18:00:00'))).toBe(true);
});
test('codes › a code is refused after its last day', () => {
  expect(isCodeValid(spring, new Date('2026-04-01T09:00:00'))).toBe(false);
});
knownBug(BUG.id, 'a code works on its last day', () => {
  expect(isCodeValid(spring, new Date('2026-03-31T10:15:00'))).toBe(true);
});

The lesson behind it

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

  • Test plan

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

  • Regression suite

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

All QA templates · Every template