# Share a Cobertura Coverage Report — The Drill-Down, Not the Percentage

Canonical: https://commareports.com/share-cobertura-report
Published: 2026-09-08

> Cobertura XML is a format, not a report. Render it with pycobertura or ReportGenerator and publish to Comma for a URL where the uncovered lines are actually visible.

# Share a Cobertura coverage report

Cobertura XML has become the lingua franca of coverage — coverage.py, gcovr,
coverlet, JaCoCo's converter and simplecov all emit it — because CI systems
know how to read it.

CI systems. Not people.

```xml
<class name="orders.service" filename="src/orders/service.py"
       line-rate="0.784" branch-rate="0.61">
  <lines><line number="42" hits="0" branch="false"/>…
```

So what gets shared is the one number the CI plugin surfaces: *78.4%*. And a
coverage percentage is the least actionable metric in engineering. It goes into
a status update, it drifts, and nobody ever opened a file because of it.

The useful artifact is the drill-down: which lines, in which file, are not
covered. That is a work queue somebody can pick up.

## Render it

```bash
# Python-friendly, single file, fast
pip install pycobertura
pycobertura show --format html coverage.xml -o report.html

# richer, multi-page, .NET-native but format-agnostic
reportgenerator -reports:coverage.xml -targetdir:report -reporttypes:Html
```

`pycobertura` gives you one self-contained page. ReportGenerator gives you a
folder with per-file source views and the uncovered lines highlighted inline —
better for reading, and it needs the folder publish path rather than the single
file.

## Publish it

Drag `report.html` (or ReportGenerator's `report/` folder) into
[the app](https://commareports.com/), or POST it:

```bash
curl -fsS -X POST "https://commareports.com/api/v1/reports" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html report.html \
        --arg t "Coverage — orders service" '{title: $t, html: $html}')"
```

For the folder version, `index.html` becomes the report body and the per-file
pages upload alongside it with their relative links rewritten to the uploaded
copies — so clicking through from the summary into a specific file works, which
is the whole reason to use ReportGenerator.

## Publish the diff, not the total

For a pull request, the project-wide figure is noise. What a reviewer needs is
whether *this change* is tested:

```bash
pycobertura diff base-coverage.xml head-coverage.xml \
  --format html --output diff.html
```

That renders only the files whose coverage moved, with the newly-uncovered
lines called out. It is a much shorter report, and it is the one that changes a
review decision.

## From CI

```bash
coverage run -m pytest && coverage xml            # → coverage.xml
pycobertura show --format html coverage.xml -o report.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 report.html \
        --arg t "Coverage — orders @ $GITHUB_SHA" '{title: $t, html: $html}')"
```

PATCHing one report id keeps a single URL per service and appends a revision per
run. Coverage that drops 4% over two months is invisible in per-build artifacts
that expire in 30 days and obvious in a revision list.

## What review adds

- **Anchored threads** on an uncovered branch, so "unreachable, guarded
  upstream" is argued once and recorded — see
  [commenting on HTML](/comment-on-html).
- **Revisions**, so the trend is evidence rather than anecdote.
- **Access per report** — a coverage report exposes your source structure and
  often source itself. See the [sharing model](/docs/sharing).

## Limits

- **Entry HTML: 5 MB.** Assets: 25 MB per file, 250 MB and 500 files total. A
  ReportGenerator run over a large codebase generates a page per source file —
  the 500-file cap is the one to watch; scope the report to the module under
  review.
- **60 requests/minute per token.**

## Try it

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

**[Publish a coverage report →](https://commareports.com/)**

### Related

- [Share a coverage report](/share-coverage-report) · [Share an lcov report](/share-lcov-report)
- [Share a JaCoCo report](/share-jacoco-report) · [Share an Istanbul report](/share-istanbul-report)
- [Coverage report links broken](/fix/coverage-report-links-broken) · [Publish from CI](/docs/ci)
