DotCov 3.0.0
See the version list below for details.
dotnet add package DotCov --version 3.0.0
NuGet\Install-Package DotCov -Version 3.0.0
<PackageReference Include="DotCov" Version="3.0.0" />
<PackageVersion Include="DotCov" Version="3.0.0" />
<PackageReference Include="DotCov" />
paket add DotCov --version 3.0.0
#r "nuget: DotCov, 3.0.0"
#:package DotCov@3.0.0
#addin nuget:?package=DotCov&version=3.0.0
#tool nuget:?package=DotCov&version=3.0.0
DotCov
Read Cobertura XML from your own code — parse, merge, threshold, and diff coverage reports. Zero package references, Native-AOT clean, and streaming rather than DOM-loading.
Getting started
dotnet add package DotCov
using DotCov;
using DotCov.Formatters;
var inputs = ReportResolver.Resolve("TestResults/"); // file or directory
var report = CoberturaParser.Parse(inputs)
.Exclude(ExclusionRules.WellKnown);
Console.WriteLine(TableFormatter.Format(report));
var gate = report.Evaluate(minLinePercent: 80, minBranchPercent: 60);
if (!gate.IsPass)
{
Console.Error.WriteLine(gate); // "NODATA: line n/a (min 80%) - …"
return 1;
}
ReportResolver.Resolve takes a file or a directory; a directory is searched for
**/*cobertura*.xml (pass a ReportPattern to change that) and Parse merges every
match, so a sharded test matrix needs no merge step. An existing directory with no match yields
no inputs and therefore an empty report; a missing path throws.
Two things the API insists on
Rates are double?. null means unanswerable — not 0.0, not 1.0. An empty report has
no rate, and treating that as 0% would fail a build that simply measured nothing.
A threshold check has four outcomes, not two. Evaluate returns a GateResult whose
Outcome is Pass, Fail, NoData, or Disabled; IsPass covers Pass alone. Branch on the
structured flags (LineBelowThreshold, BranchBelowThreshold, IsInconclusive) rather than
parsing Reason.
File identity
A report that declares several <source> roots names its files relative to one of them without
saying which. Every CoberturaParser entry point takes a FileIdentity; the default,
FileIdentity.Lexical, never reads the disk, so the same XML gives the same keys on every
machine. Such a file is keyed under the first root, listed in report.AmbiguousFiles with its
candidate roots, and warned about, and Evaluate answers NoData while any remain.
FileIdentity.ProbeSources resolves against the root that holds the file on the reading
machine's disk; FileIdentity.FromSourceRoot(root) names the root, and a root no report declares
throws UndeclaredSourceRootException.
var report = CoberturaParser.Parse(inputs, identity: FileIdentity.FromSourceRoot("src"));
What else is in the box
// Compare two reports — added / removed / modified, per-file deltas, line-level flips
var diff = CoverageDiff.Compare(
CoberturaParser.Parse(ReportInput.FromFile("before.xml")),
CoberturaParser.Parse(ReportInput.FromFile("after.xml")));
foreach (var r in diff.Regressions)
Console.WriteLine($"{r.Path}: {r.Before:P1} → {r.After:P1}");
// Async streaming, cancellable
await using var stream = File.OpenRead("coverage.cobertura.xml");
var report = await CoberturaParser.ParseAsync(stream, ct: cancellationToken);
// Per-method detail — complexity and line hits, the input behind the CRAP gate
var methods = CoberturaParser.ParseMethods(ReportResolver.Resolve("TestResults/"))
.Exclude(ExclusionRules.TestCode, keep: []);
var crap = CrapAnalysis.Analyze(methods);
var verdict = crap.Evaluate(maxCrap: 30); // NoData while any method is unscored
Exclude records what it removed: report.Exclusion holds the patterns, the keep exemptions and
the excluded paths, and JsonFormatter writes them as excluded and exclusionRules.
ExclusionRules.WellKnown covers generated code and build output, ExclusionRules.TestCode test
projects and fixtures.
TableFormatter, MarkdownFormatter, and JsonFormatter render a report for a terminal, a PR
comment, or a pipeline. BadgeFormatter.Svg(gate) and BadgeFormatter.ShieldsJson(gate) draw an
evaluated GateResult as a coverage badge, coloured by its outcome. Every numeric rendering is
invariant-formatted: 62.0% on every host, never 62,0%. CoverageSnapshot wraps a report with commit, branch, project, timestamp, and a
SHA-256 of the source file.
Parsing and safety
CoberturaParser walks the document with XmlReader — no XDocument.Load, no full-DOM
allocation, bounded memory. DTDs are ignored, never processed, and XmlResolver is null, so
there is no XXE or entity-expansion surface, and each file is capped at 50,000,000 characters
by default. Raise or remove the cap with the maxChars overloads (0 disables it).
The package has no PackageReferences at all and builds with the trim/AOT analyzers on and
warnings as errors, so AOT-cleanliness is enforced by the compiler rather than by convention.
Every public type carries XML docs — read them in IntelliSense or in the source.
Also in this family
DotCov.Tool — the dotcov CLI ·
DotCov.Fallout — Fallout build component
Feedback
Documentation · Issues · MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on DotCov:
| Package | Downloads |
|---|---|
|
DotCov.Fallout
Fallout build component that merges Cobertura reports, writes a job summary, and fails the build below your line and branch coverage thresholds. Add ICoverageReport and go. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.7.0 | 0 | 10/15/2026 |
| 4.6.0 | 2 | 10/15/2026 |
| 4.5.0 | 4 | 10/15/2026 |
| 4.4.0 | 5 | 10/15/2026 |
| 4.3.2 | 25 | 10/15/2026 |
| 4.3.1 | 27 | 10/15/2026 |
| 4.3.0 | 58 | 10/14/2026 |
| 4.2.0 | 66 | 10/14/2026 |
| 4.1.0 | 111 | 10/14/2026 |
| 4.0.0 | 75 | 10/14/2026 |
| 3.0.1 | 75 | 10/14/2026 |
| 3.0.0 | 95 | 10/13/2026 |
| 2.0.0 | 75 | 10/13/2026 |
| 1.7.1 | 97 | 10/11/2026 |
| 1.7.0 | 93 | 10/11/2026 |
| 1.6.1 | 84 | 10/11/2026 |
| 1.6.0 | 91 | 10/11/2026 |
| 1.5.0 | 87 | 10/11/2026 |
| 1.4.0 | 105 | 10/11/2026 |
| 1.3.0 | 96 | 9/29/2026 |
DotCov 3.0.0 changes three gate contracts; every number a gate decides on may move.
1. Thresholds are explicit: check, test, the Fallout target and the badge action have no default --min-line 80. Pass --min-line, --min-branch, or both (0 to 100); without either the command exits 2 before reading a report.
2. The CRAP gate needs every method scored: one unscored method makes it NODATA (exit 3). Emitters without a usable complexity attribute need --metrics.
3. File identity is deterministic: several source roots no longer trigger a disk probe; unresolved files make check, crap and test NODATA until --probe-sources or --source-root.
Fixes: contradictory condition detail and empty class summaries no longer inflate branch and line rates; condition identity no longer depends on XML packaging; CRAP rows stay per file and per overload, raising diluted scores; ./src/C.cs and src/C.cs count once; ParseAsync finishes method-only classes.
New: --exclude-test-code. Full notes: https://github.com/ANcpLua/dotcov/blob/main/docs/releases/3.0.0.md