Report tour
Five pages, one file. This is what each one is for, what the numbers mean, and what to do when they're bad. Every screenshot here is SpecTracer's own self-report — real numbers, not a mockup.
Live sample report
See the real thing — no setup required. Click below to open a fresh tab with SpecTracer's actual HTML output from this repo, showing all six pages. It's exactly what you'll get after running the tool on your own project.
Open live report in a new tabThe file itself
The report is a single self-contained HTML file. All CSS and JavaScript are inlined, and the data is rendered into the markup server-side rather than shipped as a JSON payload. The one network request is a monospace webfont from a CDN, which degrades to the system monospace if you're offline.
- Email it, archive it, attach it to a build. No server, no build step, no dependency on the repo it came from.
- Client-side hash routing (
#/,#/pyramid, …) means you can deep-link to a page and the browser back button works. - Light and dark themes, following your system preference and toggleable in the
top-right; the choice persists in
localStorage.
1 · Overview
The page that answers "how are we doing" in about three seconds.
The three headline tiles
| Tile | Numerator / denominator | Read it as |
|---|---|---|
| Declared tests matched | Satisfied @require-* layer/module pairs, over all declared pairs. |
"How much of the coverage we said we needed do we actually have?" This is the headline metric and the one fail_on: ["progress"] gates on. |
| Scenarios fully matched | Scenarios with every declared layer satisfied, over all scenarios. | Strictly harder. A scenario needing three layers and having two contributes 2/3 to the first tile but 0 to this one. |
| Tests passed | Passing results over all collected results. | Plain suite health. Counts every result, linked or not. |
The four health cards
Each card is green, amber, or red, and links through to the page that explains it. Thresholds
come from health_checks in your config — see
Health checks.
Progress amber
Declared-tests-matched percentage against your green/amber thresholds. Amber means "below target but not alarming"; red means below the amber floor.
Test pyramid green
Green while unit tests outnumber integration + E2E combined. Amber at exact parity, red when inverted.
E2E runtime green
Total E2E wall time against your time budget. This is the check that catches a suite getting slowly, invisibly slower.
Unlinked red
Orphaned results. Green at zero, amber at 1–3, red at 4 or more. Visual only — this one cannot gate CI.
2 · Test Pyramid
Test count, duration, and pass rate for each layer, drawn as proportional bars.
The shape is the point. A healthy pyramid has a long unit bar and short integration and E2E bars. What to look for:
- Bar length — relative test counts. If the E2E bar approaches the unit bar, the pyramid is inverting and CI is about to get slow.
- Duration — in the screenshot, 125 unit tests take 556ms while 53 E2E tests take 4.9s. That ~20× per-test cost difference is exactly why the shape matters.
- Pass / fail / skip pills — a layer with a high skip rate is quietly not testing anything, and no coverage metric will tell you that.
unit, integration, and
e2e in the config. If your "unit" tests spin up a database, SpecTracer will happily
report a beautiful pyramid — it can only classify what you tell it.
3 · Feature Breakdown
The traceability matrix, and where you'll spend most of your time. A searchable tree: feature → scenario → individual test result.
Row by row
| Column | What it shows |
|---|---|
| Name | Feature or scenario name. Scenario rows also carry the scenario id pill (e.g. FC-006) and, on result rows, the discovery module. |
| Completion | A bar and a satisfied/declared fraction — green at 100%, amber below. |
| Result | Rolled-up pass/fail/skip status. |
| Declared | How many @require-* pairs this row declares. |
| Actual | How many test results actually linked. This can exceed Declared — three unit tests can link to a scenario that declares one unit requirement. |
| Duration | Summed wall time of the linked results. |
Expanding a scenario
Expanding a scenario row reveals three things:
- Required-layer chips — one per declared requirement, showing the layer, the
module in parentheses, and
OKorMISSING. This is the single most actionable thing in the report:INTEGRATION (renderers) MISSINGtells you precisely what to go write. - The full Gherkin text — the Given/When/Then as written, so a reader who isn't in the code can still judge whether the scenario is worth the coverage it's demanding.
- The linked results — every test that claimed this scenario, with its layer, module, status, and duration.
Search filters the tree by name. Failure stack traces are deliberately not here — they live on the Failure Breakdown page so this view stays scannable.
4 · Failure Breakdown
Every failed test across all three layers, in one list, with feature and scenario context and the full stack trace on expand.
The value is not that it shows failures — your CI log does that. It's that a failure here arrives attached to the business scenario it broke, across layers that normally live in separate jobs. "Three failures, all under checkout" is a different triage conversation than three unrelated red lines in three log files.
5 · Unlinked Tests
Test results that carry tags but whose @scenario: values matched no scenario's
@id:.
This page is your typo detector. On a first run, a large unlinked count and a near-zero coverage number almost always mean the same thing: the tags on one side don't match the tags on the other. Common causes:
- A test tagged
@scenario:FC-42against a scenario tagged@id:FC42 - A scenario that was renamed and had its
@id:changed, orphaning its tests - Tests for a scenario that was deleted from the feature file
- A test tagged with the id of a scenario in a feature file the config doesn't include
Unlinked results still count toward the pyramid and the pass-rate tile — they ran, after all. They just don't count toward coverage.
The JSON twin
Set output_json and the same data is written as schema-validated JSON alongside the
HTML. It's built from the same internal model as the HTML renderer, so the two physically cannot
disagree.
jq -r '.summary.completion.percent' reports/spectracer-report.json
jq -r '.summary.health.status' reports/spectracer-report.json
jq -r '.summary.health.reasons[]' reports/spectracer-report.json
Use it for PR bots, custom gates the built-in checks don't cover, or posting trends to your own dashboard. Full field reference: Configuration → JSON report.
Using it in a standup
The headline numbers are designed to be said out loud. Unlike line coverage, they mean something to people who don't read code:
- To a product owner: "We haven't tested the password reset flow at all yet" — a sentence you can read straight off the Feature Breakdown.
- To a developer: "
FC-43is missing its unit test" — the required-layer chips name the exact gap. - To a lead: "We went from 78% to 72% this sprint" — usually because scenarios were added faster than tests, which is worth knowing in week two rather than week six.
Track that trend properly by posting summary from the JSON report to whatever
metrics system you already run — see Historical trends.