# What Is Cobertura XML? — The coverage.xml Format GitLab and Azure DevOps Read

Canonical: https://commareports.com/glossary/cobertura
Published: 2026-10-24

> Cobertura is the XML code coverage format behind coverage.xml: packages, classes, lines with hits, line-rate and condition-coverage. What each element means, which tools write it, and why CI systems standardised on it.

# Cobertura

**Cobertura XML is a code coverage report format — usually a file called
`coverage.xml` — that records, for every source file, which lines ran
and how many times, plus which branch outcomes were taken.** The name
comes from Cobertura, a Java coverage tool that is no longer actively
developed. The format stayed because CI systems learned to read it, and
then every other coverage tool learned to write it.

## What is in a file

```xml
<?xml version="1.0" ?>
<coverage line-rate="0.8125" branch-rate="0.5" lines-covered="13"
          lines-valid="16" branches-covered="2" branches-valid="4"
          timestamp="1729756800000" version="7.6">
  <sources>
    <source>/home/ci/project/src</source>
  </sources>
  <packages>
    <package name="cart" line-rate="0.8125" branch-rate="0.5">
      <classes>
        <class name="cart.py" filename="cart/cart.py"
               line-rate="0.8125" branch-rate="0.5">
          <methods/>
          <lines>
            <line number="12" hits="9"/>
            <line number="14" hits="9" branch="true"
                  condition-coverage="50% (1/2)" missing-branches="18"/>
            <line number="18" hits="0"/>
          </lines>
        </class>
      </classes>
    </package>
  </packages>
</coverage>
```

| Element / attribute              | Meaning                                                           |
| -------------------------------- | ----------------------------------------------------------------- |
| `<coverage>`                     | Root; overall rates and counts for the run                        |
| `<source>`                       | Base directory that `filename` paths are relative to              |
| `<package>`                      | A directory, module or namespace                                  |
| `<class filename="…">`           | One source file (or one class, in Java and .NET)                  |
| `<method>`                       | Optional; a function with its own `<lines>`                       |
| `<line number hits>`             | One executable line and how often it ran; `hits="0"` = missed     |
| `branch="true"`                  | The line contains a condition                                     |
| `condition-coverage="50% (1/2)"` | Outcomes taken / outcomes possible on that line                   |
| `line-rate`, `branch-rate`       | Fractions from 0 to 1, **not** percentages                        |
| `complexity`                     | Cyclomatic complexity, often `0` when the tool doesn't compute it |

## Things that trip people up

- **Rates are fractions.** `line-rate="0.8125"` is 81.25%. Scripts that
  print it with a `%` sign are off by a factor of 100.
- **Branches are counted per line.** A line with `if a and b:` reports
  all of its outcomes in one `condition-coverage` fraction; Cobertura
  can't tell you _which_ outcome was missed unless the tool adds a
  non-standard hint like coverage.py's `missing-branches`.
- **Paths are relative to `<source>`.** GitLab and Azure DevOps map
  `filename` onto the repository. If CI ran in a different directory, or
  the tool wrote absolute paths, the report parses but no file matches —
  coverage silently disappears from the merge request diff.
- **One file can appear as several classes.** Java and .NET emit a
  `<class>` per class, so a file with an inner class shows up twice.
  Aggregate by `filename`, not by `class name`.
- **The top-level rates aren't always reliable.** Merged or converted
  reports sometimes carry stale totals; recompute from the `<line>`
  elements when the numbers disagree.

## Cobertura vs LCOV

|                  | Cobertura                         | [LCOV](/glossary/lcov)                     |
| ---------------- | --------------------------------- | ------------------------------------------ |
| Encoding         | XML                               | Plain text, one record per line            |
| Grouping         | package → class → line            | source file → line / branch / function     |
| Branch detail    | Per line: `(1/2)`                 | Per branch: `BRDA:line,block,branch,taken` |
| Common in        | Python, .NET, Java, GitLab, Azure | JavaScript, C/C++, Rust, Flutter           |
| Read natively by | GitLab MR diffs, Azure Pipelines  | Codecov, Coveralls, editor gutters         |

Most tools can write both. If the destination is GitLab or Azure DevOps,
write Cobertura; if it is genhtml or an editor extension, write LCOV.

## Reading one without a CI system

Comma's free [coverage viewer](/tools/coverage-viewer) reads Cobertura,
LCOV and Clover in your browser: drop in `coverage.xml` and get the
overall line and branch percentages, a roll-up per directory, and every
file sorted least-covered first with its uncovered line ranges — plus a
Markdown summary for a pull request. Publish it and the report becomes a
link reviewers can comment on, file by file.

## Try it

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

**[Open the coverage viewer →](/tools/coverage-viewer)**

### Related

- [LCOV](/glossary/lcov) · [Code coverage](/glossary/code-coverage) · [JUnit XML](/glossary/junit-xml)
- [Share a coverage report](/share-coverage-report) · [Coverage report links 404](/fix/coverage-report-links-broken)
- [Glossary](/glossary)
