Coverage and the ignore policy
Fluvie gates line coverage at 97% on three library packages. They are fluvie,
fluvie_lints, and fluvie_cli. The goal is 100%. This page explains when you
may mark a line // coverage:ignore. It also says when you must write a test
instead.
Run the gate before you commit:
melos run coverage:checkIt runs every package test with coverage. Then it checks the lcov reports
against the 97% floor. Generated files never count. Those are *.g.dart,
*.freezed.dart, and *.mocks.dart.
The rule
Section titled “The rule”Test behavior. Ignore only lines that have none. If a line does real work, write a test that asserts the work. An ignore is a last resort.
Every ignore carries a reason on the same line. The gate honors three markers.
Use an inline marker for one line:
final x = legacy(); // coverage:ignore-line: reason hereUse a block marker for a run of lines:
// coverage:ignore-start: reason here... block ...// coverage:ignore-endUse a file marker for a whole file:
// coverage:ignore-file: reason hereThe gate reads the source and drops the marked lines from the total. Then it recomputes the percentage. A reason is mandatory. A bare marker hides a gap, so a reviewer must always see why.
What you may ignore
Section titled “What you may ignore”Ignore a line only when no test could assert its behavior.
- Const-constructor evaluation. The VM does not instrument a
const Foo(...)literal. Its constructor line reads as uncovered even when tests pin the object. Test the object’s fields, equality, andtoString. Then ignore the constructor line. - Diagnostic
toStringandhashCode. Prefer a one-line test. Both are cheap to assert. Both guard debug output. Ignore them only when the type is private and the string never reaches a developer. - Platform, JS, and process glue. Code that spawns FFmpeg cannot run in a unit test. Nor can a JS bridge or a real filesystem read. Cover its inputs and outputs with a fake. Then ignore the thin glue that calls the binary.
- Defensive and unreachable arms. A
defaultarm or anassertstays for safety. A valid input can never reach it. Ignore it with a reason that names why it is unreachable.
What you may never ignore
Section titled “What you may never ignore”Never ignore a line that does real work. Write a test instead.
- A branch a real input can take. Drive both sides with two tests.
- A thrown error a caller can trigger. Assert the throw with
throwsA. - A calculation, a transform, or a state change. Assert the result.
- A whole file, unless it is a platform bridge that the VM cannot load.
A hard-to-test line is a design signal. It is not a license to ignore. Inject a fake through a Riverpod override. Split the unit. Expose a pure helper. Report a stubborn defect to the implementer rather than hiding it.
Where to next
Section titled “Where to next”- Testing guide: how the suites and fakes fit together.
- Contributing overview: the workflow and the quality gate.