DotCov 4.3.0
See the version list below for details.
dotnet add package DotCov --version 4.3.0
NuGet\Install-Package DotCov -Version 4.3.0
<PackageReference Include="DotCov" Version="4.3.0" />
<PackageVersion Include="DotCov" Version="4.3.0" />
<PackageReference Include="DotCov" />
paket add DotCov --version 4.3.0
#r "nuget: DotCov, 4.3.0"
#:package DotCov@4.3.0
#addin nuget:?package=DotCov&version=4.3.0
#tool nuget:?package=DotCov&version=4.3.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, ExclusionRules.External code built elsewhere (SourceLink /_/ paths).
A report holding such files without declaring /_/ as a source root carries an
ExternalSources warning until an exclusion removes them.
report.Offenders(gate) lists the files below a failed threshold, worst first, with their
uncovered line ranges and partially covered branch lines: what to test next.
TableFormatter, MarkdownFormatter, and JsonFormatter render a report for a terminal, a PR
comment, or a pipeline; every JSON document opens with schemaVersion, command, inputs, and
warnings, and JsonFormatter.Format(report, gate, command) adds the gate object.
ExitCodes.For(outcome) maps a gate outcome to the process exit code the CLI and the Fallout
component use. 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 4.3.0 makes the TypeScript path and the crap scope explicit.
README: Vitest (accurate source branches) and c8 (zero-config wrapper around node --test) produce Cobertura for check; Jest still works.
crap is for .NET: a report in which no method has complexity (Istanbul: Vitest, c8, Jest; coverage.py) now gets a NODATA reason that says so instead of pointing at dotnet msbuild.
Full notes: https://github.com/ANcpLua/dotcov/blob/main/docs/releases/4.3.0.md