Cobertura is an open-source code coverage tool for Java, descended from jcoverage, that reports line coverage, branch coverage and McCabe cyclomatic complexity. Its defining characteristic is offline instrumentation: rather than modifying classes as they load, Cobertura runs as a separate build step that rewrites compiled `.class` files and writes the instrumented copies to a new directory, alongside a serialised datafile — `cobertura.ser` — holding the structural metadata for every instrumented class. Tests then execute against those instrumented classes with the Cobertura runtime on the classpath, and a JVM shutdown hook flushes the accumulated hit counts back into that datafile. Reporting is a third step joining the datafile to the original sources.
That three-phase shape — instrument, run, report — explains almost everything teams struggle with. The instrumented output directory must come before the original classes on the runtime classpath, or the tests run against uninstrumented code and the report shows zero. Forked test JVMs need the datafile location passed explicitly as a system property. Applications in a servlet container only flush counts on a clean shutdown. And instrumented classes must never be packaged into a release artefact, since they carry a hard dependency on the Cobertura runtime.
Cobertura's other legacy is its report format. The `coverage.xml` it emits became a de facto interchange standard well beyond Java: Jenkins, GitLab pipeline coverage visualisation, and Python's coverage.py and pytest-cov all read or write Cobertura XML. The Java tool itself, however, has been effectively dormant since its 2.1.1 release in 2015, its Maven plugin is retired, Gradle support only ever came from third-party plugins, and it cannot handle class file versions from modern JDKs. So the practical work today splits two ways: keeping an existing Cobertura estate honest, and planning a controlled migration onto JaCoCo without losing coverage history.
Why this skill matters now
A large number of long-lived Java builds still run Cobertura, and they are usually the builds nobody wants to touch — Ant scripts, older application servers, regulated systems where the build has been signed off and change is expensive. Those estates still need someone who can read a coverage report, explain why a module reports zero, merge datafiles across a split test run, and adjust a threshold without breaking the release pipeline.
At the same time the tool has a real ceiling. It has had no substantive release since 2015, its Maven plugin has been retired by its maintainers, and it does not support the bytecode produced by current JDKs — which means the moment a project's language level moves, the coverage step is what breaks. Teams hit this during an upgrade, under time pressure, with no plan.
That is exactly the skill worth having: knowing Cobertura well enough to keep it working while it must work, and well enough to migrate off it deliberately — mapping instrumented-build assumptions onto an agent-based model, translating threshold rules, reconciling the two tools' different definitions of a covered line, and keeping the Jenkins and SonarQube reporting continuous through the change. The Cobertura XML format also survives its own tool, so understanding it remains useful long after the Java implementation is retired from a build.