# lcov vs Cobertura: coverage report formats
> lcov is text and names each branch; Cobertura is XML with a branch count per line. The same run in both formats, and which tools read which.
Web page: https://supercov.com/compare/lcov-vs-cobertura · Published 2026-10-12
All Supercov pages for agents: https://supercov.com/llms.txt · Full text: https://supercov.com/llms-full.txt
## Which format should you produce?
Produce the one the tool reading it accepts; most coverage tools can write
both. lcov is plain text with one record per line, and it names each branch.
Cobertura is XML, and gives a branch count per line. When both are accepted,
lcov keeps more detail and is easier to merge.
## The same run in both formats
One Jest run on one file, written with both reporters. From the lcov file:
```text
SF:src/access.js
FN:8,label
FNDA:1,label
DA:9,1
LF:5
LH:5
BRDA:9,3,0,1
BRDA:9,3,1,0
BRF:7
BRH:6
end_of_record
```
From the Cobertura file:
```xml
```
Both say line 9 ran once and half its branches were taken. Only lcov says
which half: `BRDA:9,3,1,0` is the second branch, taken 0 times.
## How they differ
| | lcov | Cobertura |
| --- | --- | --- |
| Syntax | Text, one record per line | XML |
| Lines | `DA:line,hits` | `` |
| Branches | `BRDA`, one record per branch | `condition-coverage`, a count per line |
| Functions | `FN` and `FNDA` | `` |
| Totals | `LF`, `LH`, `BRF`, `BRH` per file | `line-rate` and `branch-rate` at every level |
| File paths | `SF:` per file | `filename`, relative to a `` |
| MC/DC | `MCDC`, with `MCF` and `MCH` per file, from lcov 2.0 | None |
| Merging | `lcov --add-tracefile` | Needs a tool that understands the XML |
Neither format records which test ran a line. Only lcov 2 has a record for
MC/DC, and only readers that ask for it (`--mcdc-coverage`) read it.
## Who reads which
Check the tool that consumes the report:
- Codecov [accepts both](https://docs.codecov.com/docs/supported-report-formats),
and JaCoCo XML. So does Coveralls; see
[Codecov vs Coveralls](https://supercov.com/compare/codecov-vs-coveralls.md).
- GitLab's [coverage view](https://docs.gitlab.com/ci/testing/code_coverage/)
in merge requests reads Cobertura and JaCoCo XML, not lcov.
- SonarQube reads lcov for JavaScript and TypeScript, and Cobertura-style XML
from coverage.py for Python.
## Paths are the usual failure
A report that uploads but shows no coverage usually has paths the reader
cannot match to the repository. In the Jest run above, `` held the
absolute path of the project on the machine that ran the tests. Generate
reports from the repository root, and prefer repository-relative paths.
Cobertura is also the name of a Java coverage tool, last released in 2015.
The format outlived it. See [JaCoCo vs Cobertura](https://supercov.com/compare/jacoco-vs-cobertura.md).
## Export both from Supercov
```sh
npx supercov runs report --format lcov --output coverage/lcov.info
npx supercov runs report --format cobertura --output coverage/cobertura.xml
```
Supercov writes both from one run, with repository-relative paths and a
stable order. A line's hit count is 1 or 0,
because Supercov records that a line ran, not how often. Per-test coverage and
MC/DC stay in Supercov's own report, since neither format can hold them.
Example evidence: [fixture source, commands and recorded results (JSON)](https://supercov.com/downloads/tool-comparisons-2026-10-12.json). Measured October 12, 2026 with Supercov 4.3.0. These small examples are not a performance benchmark or a general conformance test.