Test coverage
Measured on 2026-08-16 at commit a81004f930cb, by the release that published this site.
The whole test suite covers 95.2% of the workspace's 14,695 statements. The unit layer alone reaches 87.9%, and the integration layer's instrumented binary 85.9%; the two overlap, so the total is every profile merged rather than either of them added up.
Every number on this page is measured rather than written. Each module's own tests produce one
go test -covermode=atomic profile (with -coverpkg=./... for the CLI module). The black-box integration suite
contributes one more: its harness builds the real dispat binary with -cover when DISPAT_COVERDIR is set and points
every invocation's GOCOVERDIR there, so the flows only that suite exercises (the app/cli composition, the finalize
phase, the commands, signal handling) count too. The profiles are then merged block by block, where a block compiled by
two test binaries counts once and is covered if either reached it, and the merged total becomes the badge on the
repository README.
The badge and this page are therefore the same number, taken from the same run: the one that gated the release which published this site.
By module
| Module / package | Statements | Covered | Coverage |
|---|---|---|---|
pkg/ccme | 1,328 | 1,285 | 96.8% |
pkg/manifest | 170 | 170 | 100.0% |
pkg/models | 213 | 207 | 97.2% |
pkg/scanner | 1,061 | 1,016 | 95.8% |
pkg/writer | 2,654 | 2,476 | 93.3% |
services/dispat | 9,269 | 8,842 | 95.4% |
| the module itself | 1 | 1 | 100.0% |
internal/app | 2,638 | 2,464 | 93.4% |
internal/changelog | 168 | 165 | 98.2% |
internal/cli | 711 | 708 | 99.6% |
internal/config | 1,833 | 1,769 | 96.5% |
internal/filter | 175 | 174 | 99.4% |
internal/fsx | 23 | 13 | 56.5% |
internal/github | 170 | 158 | 92.9% |
internal/gitx | 549 | 508 | 92.5% |
internal/globx | 14 | 14 | 100.0% |
internal/graph | 111 | 109 | 98.2% |
internal/ignore | 64 | 64 | 100.0% |
internal/model | 45 | 45 | 100.0% |
internal/plan | 1,587 | 1,528 | 96.3% |
internal/release | 832 | 799 | 96.0% |
internal/script | 47 | 44 | 93.6% |
internal/selfupdate | 301 | 279 | 92.7% |
The statements still uncovered are almost entirely single-line defensive branches: a write/fsync/chmod failing
mid-atomic-write, a git subprocess failing for a reason its caller cannot produce on purpose, the second half of a
double failure (a rename that fails and the rename undoing it failing too), and internal "this cannot happen" guards
behind data the same function already validated. Reaching them would mean asserting on
error text rather than on behaviour, so they are left uncovered deliberately.
The per-package test inventory (what each package's suite actually asserts) is in Architecture / Testing, and what the suite did rather than what it reached is in test results.
Reproducing
The whole measurement is three commands from the monorepo root, and they are the ones the release workflow runs:
dispat run tests --since all # every module's profile and go test -json log, into coverage/
sh scripts/coverage-badge.sh # merges the profiles; writes the badge JSON
go run github.com/yohimik/dispat/tools/testreport build # writes packages/docs/data/report.json, read by this page
--since all is not optional. A run selected by a --since window tests part of the monorepo, so a total from it
would be a number about whichever packages happened to change. That is why the badge is computed by the release
workflow rather than by the per-commit test workflow.
Rebuilding this site with packages/docs/data/report.json in place is what puts the figures back on the page; without
one, the prose stays and the tables are left out.
What each layer contributes
The unit layer covers every package against in-memory fakes. On its own it stops short of the total, because the
composition (the compiled binary, the finalize phase, the run/test/preview commands, real git over a process boundary,
SIGINT handling) lives exclusively in the
black-box integration suite, which asserts
behaviour (git state, JSON log events, execution timelines) rather than statements. Instrumenting the binary it drives
is what folds that behaviour back into the statement numbers above without compromising the suite's black-box design:
the harness only sets two environment knobs, and with DISPAT_COVERDIR unset (the default, and every local go test)
the binary is built exactly as released.
The suite's own status and per-area summary are in test results, with the claim-by-claim matrix in the test plan.