skip to content

How do you configure the jacocoTestReport task to produce an XML report for CI and an HTML report for humans?

level: middleimportance: must knowfreq 65%

answer

  1. reports { html / xml / csv }
  2. required is a lazy Property<Boolean>
  3. xml off by default, html on
  4. xml.required.set(true) for CI
  5. outputLocation to redirect

basics

~10 s

In the jacocoTestReport task, set reports { xml.required.set(true); html.required.set(true) }. XML is for tools like SonarQube/Codecov; HTML is the browsable report. You can also turn off csv.

solid answer

~40 s

The `jacocoTestReport` task exposes a `reports {}` container with `html`, `xml`, and `csv` sub-reports. Each has a lazy `required` Property<Boolean> you toggle, and an output location property. In modern Gradle you set them via the Provider API: `xml.required.set(true)`, `html.required.set(true)`, and usually `csv.required.set(false)`. XML is the machine-readable format CI tools (SonarQube, Codecov, Coveralls) ingest; HTML is the navigable per-class report developers open. By default HTML is on and XML/CSV are off, so enabling XML is the key step for CI. You can redirect outputs with e.g. `xml.outputLocation.set(layout.buildDirectory.file("reports/jacoco/report.xml"))`. Because `required` is a lazy `Property`, prefer `.set(...)` (or assignment in Kotlin) over the older `isEnabled` flag.

code

kotlin · 7 lines
kotlin
tasks.jacocoTestReport {
    reports {
        xml.required.set(true)
        html.required.set(true)
        csv.required.set(false)
    }
}

go deeper

for a junior

Know the three report types and that you toggle them in reports {}.

for a middle

Explain defaults (html on, xml/csv off), the lazy required Property, and why CI needs XML.

for a senior

Discuss redirecting outputLocation for stable CI paths and configuration-cache-friendly Provider usage.

for a principal

Standardize report formats across a multi-module org so every module emits XML at predictable paths for a central quality gate.

## The `reports {}` block `jacocoTestReport` is a `JacocoReport` task. It carries a `reports` container (`JacocoReportsContainer`) holding three configurable report types: - **`html`** — a browsable, drill-down report (`build/reports/jacoco/test/html/index.html`). On by default. - **`xml`** — a single machine-readable file consumed by coverage services and quality gates. **Off by default.** - **`csv`** — a flat CSV summary. Off by default; rarely useful. ## Lazy `required` properties Each sub-report exposes `required`, a `Property<Boolean>` from Gradle's Provider API, plus an `outputLocation` (a `RegularFileProperty` for single-file reports like xml/csv, or a `DirectoryProperty` for html). Because these are lazy, you configure them with `.set(...)`: ```kotlin tasks.jacocoTestReport { reports { xml.required.set(true) html.required.set(true) csv.required.set(false) } } ``` In Kotlin DSL you can also use property assignment (`xml.required = true`) thanks to Gradle's lazy-property assignment support. The legacy `isEnabled`/`enabled` API still works but is discouraged. ## Why XML matters for CI Dashboards and quality gates don't parse HTML. They read the JaCoCo **XML**: SonarQube's `sonar.coverage.jacoco.xmlReportPaths`, Codecov/Coveralls uploaders, etc. So in a CI build you almost always flip `xml.required` to `true`. HTML stays useful as a build artifact developers can download and browse. ## Customizing output locations Defaults are fine, but you can pin paths so CI config is stable: ```kotlin reports { xml.required.set(true) xml.outputLocation.set(layout.buildDirectory.file("reports/jacoco/test/jacocoTestReport.xml")) html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco/test/html")) } ``` ## Common gotcha Enabling XML doesn't *run* the report — you still invoke `jacocoTestReport`. And the report's inputs are the execution data + classes; if no tests ran, there's no `.exec` and the report is empty or skipped.

  • Which report format does SonarQube or Codecov consume, and why not HTML?
    They consume the XML report (it's structured/machine-readable). HTML is meant for human browsing and isn't a stable parse target.
  • What's the difference between `xml.required.set(true)` and the old `xml.isEnabled = true`?
    `required` is a lazy `Property<Boolean>` from the Provider API and is the modern, configuration-cache-friendly form; `isEnabled` is the deprecated eager flag that did the same thing.

saying these in an interview costs you the question

  • Assuming XML is on by default — it is off; HTML is on.
  • Configuring `reports {}` on the wrong task (e.g. on `test`) instead of `jacocoTestReport`.

context