Line and branch coverage.
Measured on your machine.
Nimbus collects coverage while it executes your Salesforce Apex tests locally - lines, methods, and both sides of every branch. No org, no deploy, no waiting for a Tooling API query to tell you what you already could have known before you pushed.
Nimbus executes your Salesforce Apex tests on your machine and measures what they touched while it does it.
This is the tool page: what gets measured, which report formats come out, and how to gate on it. For wiring coverage into a pipeline - GitHub Actions, GitLab, SonarQube, Codecov - see CI integration. For the argument about what coverage is actually worth, there is a separate opinion piece.
What gets measured
Coverage is collected by the interpreter as it runs, not reconstructed afterwards. Add --coverage to any nimbus test invocation and the run records three things.
Lines. A hit count per executable line. The denominator comes from static analysis of the parsed source, not from whichever lines happened to be executed - so a line nothing reached still counts against you.
Methods. Execution counts per method, rolled up per class, so you can see which methods the suite never entered at all.
Branches. For every if, switch, and ternary, Nimbus tracks the true side and the false side separately. A branch only counts as covered when both sides were taken. Salesforce's own metric does not do this - a test that only ever exercises the happy path shows the branch as fully covered there, and as half covered here.
Reports break down per file, per class, and per method. Nimbus does not attribute individual lines back to the individual test that covered them.
nimbus test "CalculatorTest.*" --coverage
# Code Coverage Summary
#
# Lines: 46 / 3835 ( 1.2%)
# Methods: 14 / 14 (100.0%)
# Branches: 3 / 3 (100.0%)
#
# Coverage by Class:
#
# Calculator.cls 100.0%
# |- add 100.0%
# |- divide 100.0%
# |- factorial 100.0%
# |- isEven 100.0%
# |- multiply 100.0%
# '- subtract 100.0%Report formats
One flag, five outputs. Nimbus picks the writer from the file extension you pass to --coverage-report, and --coverage-report implies --coverage, so you never have to pass both.
Summary in the terminal
Line, method, and branch totals plus a per-class and per-method breakdown, printed after the run. Nothing to open, nothing to upload.
nimbus test --coverageThe machine-readable report
Per-file hit counts, the executable-line denominator, and per-line branch status (trueExecuted / falseExecuted / covered). This is also the input format for nimbus coverage diff.
--coverage-report coverage.jsonBrowsable report
Line, method, and branch percentages up top, then every file with its own bar. Useful as a CI artifact when someone asks where coverage actually went.
--coverage-report coverage.htmlSonarQube, Codecov, quality gates
The standard coverage interchange format, with branch-rate and condition-coverage attributes filled in from the same data the console prints.
--coverage-report coverage.xmlTest results alongside coverage
Not a coverage format - the companion one. Pass it in the same run so your CI dashboard gets pass/fail history and coverage from a single invocation.
--results-xml results.xmlThe console summary and the JSON report are Free. HTML and the XML formats are Pro.
--coverage-output controls what gets printed inline - console (default) or json. It is independent of --coverage-report, which writes a file.
Coverage and JUnit results can be produced in the same run, so CI does not need a second pass over the suite to get both.
# Console summary (Free)
nimbus test --coverage
# JSON report (Free)
nimbus test --coverage --coverage-report coverage.json
# HTML report (Pro)
nimbus test --coverage --coverage-report coverage.html
open coverage.html
# Cobertura XML (Pro)
nimbus test --coverage --coverage-report coverage.xml
# Coverage and test results in one run (Pro)
nimbus test \
--coverage --coverage-report coverage.xml \
--results-xml results.xmlCoverage diff
A repository-wide percentage tells a reviewer almost nothing. What a reviewer wants is the delta: did this pull request stop covering something that used to be covered?
nimbus coverage diff takes two JSON reports - a baseline and the current one - and reports the overall line coverage delta, the per-file regressions and improvements, and the specific line numbers that went from covered to uncovered.
Pass --fail-on-drop and the command exits non-zero when overall coverage decreased. That is the whole flag surface - two positional arguments and one gate.
The diff is computed on line coverage. Branch data is present in the JSON reports themselves, but the delta report is line-based.
# Baseline on main
nimbus test "*" --coverage-report base.json
# Then the branch
nimbus test "*" --coverage-report pr.json
# Compare, and fail the build on a drop
nimbus coverage diff base.json pr.json --fail-on-drop
# Coverage: 78.4% -> 76.9% (-1.5%)
#
# Regressions:
# classes/AccountService.cls 82.0% -> 71.4% (-10.6%) newly uncovered: 44, 45, 46, 91
#
# Improvements:
# classes/LeadRouter.cls 61.0% -> 68.2% (+7.2%)Coverage as a gate
Coverage that nobody enforces is a number on a dashboard. Nimbus exposes it as an exit code in three places.
Deploy. nimbus deploy --min-coverage N runs the local Apex tests against the snapshotted payload and refuses to continue if local line coverage is below the threshold - before Salesforce is contacted at all. See gated deploys.
Release validate. The same --min-coverage gate applies to nimbus release validate, and the threshold can be pinned in a named release profile instead of being retyped per invocation. See release management.
Pull requests. nimbus coverage diff --fail-on-drop covers the case a fixed threshold misses: a project sitting comfortably at 88% that quietly slides to 84% one merge at a time.
Both --min-coverage gates measure line coverage.
# Refuse the deploy under 80% local line coverage
nimbus deploy --target-org staging \
--source-dir force-app \
--min-coverage 80
# Same gate on a validation run
nimbus release validate \
--release-profile production \
--min-coverage 80
# PR gate: no regression allowed
nimbus coverage diff base.json pr.json --fail-on-dropIn the editor
A coverage report you have to go and open is a report you check once a quarter. Both editor integrations put the same data in the gutter of the file you are already looking at.
Turn on nimbus.coverage.enabled and every run annotates the editor: executed, missed, or a partially taken branch. Method-level percentages appear inline after each signature, so you can see which method is thin without leaving the file.
The plugin adds coverage gutters plus a baseline snapshot: run a coverage pass, set it as the baseline, then toggle the delta overlay to see which lines your change covered - and which it stopped covering.
JetBrains pluginAbout the 75%
Salesforce requires 75% Apex code coverage to deploy to production. Every Salesforce developer knows the number, and most have watched a release window close because a deployment validation discovered the org disagreed with their estimate.
Nimbus moves that discovery earlier. The same suite that produces your local coverage number runs in seconds on your machine, in your editor, and in CI - so the 75% conversation happens while you are writing the code, not while a validation job is running against production.
The local number is a strong signal, not a substitute for the org's. Nimbus measures the code it executed locally; Salesforce measures what it executed in the org. Use --min-coverage to catch the obvious failure before you spend a deploy on it.
The more interesting problem is that 75% is a floor, and floors get gamed. A test that calls every method and asserts nothing clears it. So does a test that only ever walks the happy path.
That is what branch coverage is for. It is the cheapest available signal that your suite has actually been down both sides of a decision, and it is the number worth watching once the line percentage stops moving.
We wrote up the longer version of this argument separately.
Apex code coverage is not a test strategyKnow the number before the org does.
Line, method, and branch coverage from the test run you were going to do anyway. HTML, JSON, and Cobertura out. A diff for pull requests and a threshold for deploys.