Share a .NET coverage report

The pipeline is three steps, and only the last one produces something a human reads:

dotnet test --collect:"XPlat Code Coverage"
# → TestResults/<guid>/coverage.cobertura.xml   (data, not a report)

dotnet tool install -g dotnet-reportgenerator-globaltool
reportgenerator \
  -reports:"**/coverage.cobertura.xml" \
  -targetdir:"coveragereport" \
  -reporttypes:Html

What you get is coveragereport/index.html, a page per class with the hit counts in the gutter, report.css, main.js and icons. The drill-down is the report, and it's the first thing to die when someone attaches index.html to a message.

Publish the directory

Drag coveragereport/ (or a zip of it) into Comma:

  • index.html becomes the report body.
  • Every per-class page and the CSS/JS upload alongside, and the relative links between them are rewritten to the uploaded copies — so clicking from the summary into OrderService still works.
  • The sortable summary table keeps working: scripts run inside a sandboxed iframe with no same-origin access. See interactive HTML reports.

Nothing needs a local web server, which is the other reason these reports usually stay on the machine that generated them — see serving an HTML file locally.

From CI

reportgenerator -reports:"**/coverage.cobertura.xml" \
  -targetdir:coveragereport -reporttypes:Html

curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html coveragereport/index.html \
        --arg title "Coverage — $GITHUB_SHA" '{title: $title, html: $html}')"

One report id per branch keeps one URL and appends a revision per run. The interesting question about coverage is never the number, it's the direction — and revisions answer that without buying a dashboard. See publishing from CI and the GitHub Actions or Azure DevOps walkthroughs.

If your pipeline already uses -reporttypes:HtmlInline_AzurePipelines for the built-in tab, keep it — add the plain Html output alongside and publish that, so the report survives the artifact retention window.

What review adds

  • Anchored threads on an uncovered branch, in the source view — commenting on HTML.
  • Revisions, so "coverage dropped" is a diff rather than an assertion.
  • Access per report — private, team, domain-gated or link-based. See sharing & access control.

Limits

  • Entry HTML: 5 MB. Assets: 25 MB per file, 250 MB and 500 files total. A large solution can exceed 500 class pages — ReportGenerator's -classfilters: and -assemblyfilters: keep the published report to the part actually under review.
  • 60 requests/minute per token.

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history.

Publish a coverage report →

Related