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
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.
- All my tests pass
- No uncaught errors
// 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.',
};
// 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');
}
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.
More QA templates
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.