Free tool

Test Register

The scenarios you're relying on, tied to the acceptance criteria and sliced stories they verify. When a spec changes, every test generated from it is flagged stale — because in 2026 the expensive failure isn't the test you forgot to write, it's the one written from a spec that has since moved.

It spans three stages of the pipeline — definition, delivery cadence, and feedback — which is why the QA ring runs alongside them rather than owning one.

Nothing leaves your browser. Scenarios, links, and statuses are stored in localStorage on this device — there's no account and no server.

Running a register when the machine writes the tests

A test register used to be a bureaucratic artifact: a spreadsheet somebody updated the week before an audit. It's worth keeping again for one reason. When a model drafts your Playwright specs, the link betweenwhat we agreed to build and what the suite checks stops being obvious. The code compiles, the suite is green, and nobody can tell you whether the green covers the criterion you shipped last Thursday or the wording it had three revisions ago.

The register's job is to hold that link explicitly, so drift is loud. You register a scenario, anchor it to an acceptance criterion or a sliced story, and the tool takes a snapshot of that source's exact wording. Later — after somebody sharpens a criterion in the spec, or deletes a story that got absorbed into another slice — the register compares the snapshot to what's there now and flags every scenario built on the old text.

Four statuses, and only three of them are yours

You set the first three. The fourth sets itself.

Not automated
Written down, anchored to a criterion or a story, no spec file yet. A named gap you can schedule beats an unnamed one you rediscover in production.
AI-drafted
A spec file exists and a model wrote most of it. It runs and it goes green. Nobody has confirmed it asserts the thing the criterion actually asks for.
Human-reviewed
Someone read the generated test next to the criterion and agreed. This is the only status where the coverage number means what you'd like it to mean.
Stale
A linked criterion or story changed — or was deleted — after the test was written. Derived on every load from the stored snapshot, so it can't be forgotten to be set.

The rule that makes the whole thing work: regenerating resets review. When you regenerate a spec from updated wording and mark it regenerated here, the scenario drops back to AI-drafted — even if a human had reviewed it an hour earlier. That review was of different code asserting different words. Keeping the badge would be a lie, and it's the exact lie that lets a suite stay green while quietly ceasing to check the thing it was written for.

Sources that were deleted can't be regenerated — there's no current wording to re-baseline against. Those you unlink deliberately, and the register won't let a scenario end up anchored to nothing: link something else, or delete the scenario and admit the coverage is gone.

Spec paths that survive a regeneration

Each scenario carries a path to the spec file that runs it — a pointer, not a promise; the tool never checks whether the file exists. Three conventions make that pointer worth storing:

  • Mirror the app's domain structure, not your test framework's folders.

    If the product has orders, billing, and admin, so does e2e/. A person looking at a failing suite should be able to guess the file from the feature name.

  • One registered scenario ↦ one test() block.

    When a scenario goes stale you want to open exactly one block, read what it asserts, and regenerate it. A single test() covering four scenarios makes drift unfixable in place.

  • One file per feature area, not per criterion.

    e2e/orders/discount-code.spec.ts holds every discount-code scenario. Files per criterion sprawl past the point where anyone can find anything; files per epic get too big to regenerate safely.

So a discount-code scenario for Donut CRM lands ate2e/orders/discount-code.spec.ts, and when its criterion is reworded you know precisely which file to hand back to the model — and precisely which block inside it.

Why the coverage view is a list, not a percentage

Coverage percentages are the most gameable number in engineering. 84% tells you nothing you can act on: not which criterion is naked, not whether the covered 84% is covered by tests generated from wording that's still current. So the register leads with the gaps — the criteria and stories with no scenario at all, then the ones whose only coverage is stale. The fraction is there, in small type, underneath.

That middle bucket is the interesting one. "Covered by stale tests only" is AI-era test debt made visible: work that looks done on every dashboard and verifies a spec nobody ships anymore. A scenario contributes to coverage only when the whole scenario is current — one drifted link poisons it, because a test half-generated from an old criterion isn't trustworthy about the other half either.

Drift detection here is deliberately literal: any change to the wording, down to a typo fix, flags the scenario. Over-flagging costs one click on "mark regenerated." Under-flagging costs an escape, found by a customer. That trade isn't close.

Where it sits in the pipeline

The register reads — and never writes — two neighbouring tools. Acceptance criteria come from the Spec Builder; sliced stories come from the Vertical Slicer. Write criteria there, cut slices there, register the scenarios here, and the three stay joined by stable ids rather than by copy-paste. Editing a criterion in the Spec Builder is what makes a scenario go stale in this tool — that's the feature, not a synchronisation bug. Reload the register after you've edited a spec elsewhere and the flags catch up.

0:000:00