Runs the test suite with runtime-attributed line coverage in one command:
mix test.qloverPlain mix test is unchanged. A successful full run records executable
lines and their runtime test-file owners. A test-only edit reruns the edited
file, replaces its old hits, and combines them with other files' unchanged
hits. Deleting a file gates directly from surviving evidence. Changed code,
helpers, dependencies, and incompatible or missing evidence use a
conservative refresh. Passing tests save complete attributed evidence even
when coverage is incomplete; the coverage gate still fails. Failed tests
never advance a baseline.
Shared setup coverage is refreshed with focused runs. File-loading hits belong to the loaded test file, including its tracked child processes. Deleting files refreshes shared setup without executing remaining tests.
There is no stale manifest involved: the file list comes from qlover's
own evidence and reference graph, so selection is deterministic across
worktrees, and a host test alias injecting
--stale cannot shrink it (--no-stale is passed first, which wins the
duplicate-flag resolution).
Extra arguments are appended to focused selection (mix test.qlover --seed 0). Filtering flags cannot produce reusable coverage, and explicit files
cannot restrict a full baseline. --no-stale forces a full
suite run and refreshes the baseline. --dry compiles pending changes and
prints the files qlover would select, with their selection reasons, without
running tests or updating the coverage baseline. The flags --stale,
--cover, --no-cover, --export-coverage, --failed, --partitions,
--dry-run, --no-compile are managed by the task and rejected when passed
explicitly.
Path overrides (mirroring mix qlover):
--baseline PATH- baseline file (default:cover/.qlover_baseline)--export PATHand--expansion-export PATH- legacy cover scratch export locations; attributed runs use a private, versioned report instead of.coverdata, which has no file ownership.
Test failures abort before gating and never update the baseline. Scratch
exports are deleted after gating (and any leftovers removed before each
run), so a later mix test.coverage never unions a stale partial into a
full report.
Each invocation reports qlover: ran X tests; didn't run Y tests. Counts
come from ExUnit (including generated tests and doctests); unchanged files
reuse counts stored in the baseline and shared cache. ExUnit skips and
exclusions are included in Y and reported separately. Failed runs also
print the summary. If a run aborts without reporting counts, unknown
values are labelled rather than estimated. Older baselines receive one
full run to collect counts.
Coverage percentages are rounded down to two decimals so incomplete
coverage never displays as 100.00%. Threshold checks use exact counts.
The --qlover flag spelling
Mix does not let dependencies add flags to mix test, but the same
spelling is one alias away in your own mix.exs:
defp aliases do
[
test: fn
args ->
if "--qlover" in args do
Mix.Task.run("test.qlover", args -- ["--qlover"])
else
Mix.Tasks.Test.run(args)
end
end
]
endWith that, mix test --qlover gates while bare mix test (including
mix test test/foo_test.exs) stays vanilla.