Code Coverage #
Running coverage #
python3 dev/coverage.py
This prints a line-coverage summary with exclusions applied (see below).
Other formats #
python3 dev/coverage.py --lcov # writes coverage.lcov
python3 dev/coverage.py --html # writes coverage-html/html/index.html
python3 dev/coverage.py --json # writes coverage.json
python3 dev/coverage.py --all # all of the above + summary
python3 dev/coverage.py --open # --html and open in browser
The summary, LCOV, and HTML outputs all apply exclusions. HTML is rendered by
genhtml (from the lcov package, included in the nix dev shell) from the
post-processed lcov file; excluded lines appear as uninstrumented (white, not
red). JSON is generated directly by cargo-llvm-cov and does not reflect
exclusion comments.
To disable exclusion processing:
python3 dev/coverage.py --no-excl
Excluding lines from coverage #
Some lines are legitimately unreachable or only reachable in error conditions
that are impractical to trigger in tests (e.g. panic! arms, Display impls
for error types, exhaustive match arms over internal enums). panic! /
unreachable! arms are ignored automatically (see Auto-ignored lines);
mark everything else with coverage exclusion comments so it doesn’t drag down
the reported percentage.
Exclude a single line #
Err(e) => panic!("internal error: {e}"), // cov:excl-line
The comment can appear anywhere on the line. (Lines containing panic!( or
unreachable!( are already ignored automatically, so the comment is optional
here — it is shown only to illustrate the syntax.)
Exclude a block #
// cov:excl-start
impl fmt::Display for InternalError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
// cov:excl-stop
The start and stop lines themselves are also excluded.
Auto-ignored panic/unreachable lines #
Lines containing panic!( or unreachable!( are recognized automatically
and removed from coverage statistics — no comment required. They are kept in a
separate category from explicit exclusions: because such a line may or may not
be hit depending on which tests run, it is neither counted as covered nor as
uncovered, and it is never reported as a wrong exclusion. An explicit
exclusion that is nonetheless executed by a test is reported as a wrong
exclusion (and highlighted in HTML reports) so it can be fixed.
When to use exclusions #
Use exclusions sparingly and only for code that genuinely cannot be covered:
panic!/unreachable!arms that guard against impossible states (handled automatically, no comment needed)- Trait impls required by the type system but never exercised at runtime
(
Debug,Display,Fromfor internal error variants) - Exhaustive match arms on internal enums where one variant only exists for forward-compatibility
Do not exclude code just because it is hard to test. If a branch is hard to reach, that is a signal to either write a targeted test or reconsider the design.