skip to content

HTML & JUnit-XML Reports

The HTML and JUnit-XML reports the Test task produces, where they land, and why CI consumes the XML. Asked because a build server needs the XML while a human needs the HTML.

on this pageshow

questions

5

After running `./gradlew test`, where does Gradle put the human-readable test report and the machine-readable results, and which one do you open in a browser?

level: juniorimportance: must knowfreq 62%

answer

  1. HTML under build/reports/tests/<task>
  2. XML under build/test-results/<task>
  3. index.html = human view
  4. TEST-*.xml per class = CI view
  5. per-task-name directories

basics

~10 s

Gradle writes an HTML report under build/reports/tests/test/ (open index.html in a browser) and machine-readable JUnit-XML under build/test-results/test/. You open the HTML in a browser.

solid answer

~30 s

Each `Test` task produces two outputs. The **HTML report** lands in `build/reports/tests/<taskName>/` — open `index.html` to browse packages, classes and failures with stack traces and stdout. The **JUnit-XML results** land in `build/test-results/<taskName>/` as one `TEST-*.xml` per test class; these are for tools (CI, IDEs), not humans. For the default `test` task that's `build/reports/tests/test/index.html` and `build/test-results/test/`. The HTML report is actually generated *from* the binary results Gradle records during the run, so the XML and HTML are two renderings of the same data. The directories are keyed by task name, so a second `Test` task like `integrationTest` gets its own `build/reports/tests/integrationTest/`.

code

bash · 5 lines
bash
./gradlew test
# browse the HTML report
open build/reports/tests/test/index.html
# machine-readable results for CI
ls build/test-results/test/   # TEST-com.acme.FooTest.xml ...

go deeper

for a junior

Name the two locations and that index.html is the browsable one; that's enough.

for a middle

Add that dirs are keyed by task name and the XML is per-class TEST-*.xml consumed by tools.

for a senior

Explain HTML/XML are both derived from a binary result store, enabling later aggregation.

for a principal

Frame the binary-vs-rendered split as the basis for cross-module report aggregation and reproducible CI artifacts.

## Two outputs per Test task Every task of type `Test` in Gradle emits two distinct artifacts when it runs: - **HTML report** — a browsable site for humans, written to `build/reports/tests/<taskName>/`. The entry point is `index.html`. It shows pass/fail counts, duration, a per-package and per-class breakdown, failure stack traces, and captured stdout/stderr. - **JUnit-XML results** — machine-readable XML, written to `build/test-results/<taskName>/`. Gradle writes one file per test class named `TEST-<fully.qualified.ClassName>.xml`. CI servers, IDEs, and aggregation tools parse these. Note the two different roots: `build/reports/...` for the rendered HTML and `build/test-results/...` for the raw XML. People frequently mix them up. ## Per-task directories The `<taskName>` segment means outputs are namespaced by the task. The default `test` task gives `build/reports/tests/test/` and `build/test-results/test/`. If you register a second test task (e.g. `integrationTest`), it writes to `build/reports/tests/integrationTest/` and `build/test-results/integrationTest/` automatically — no collisions. ## Where the data comes from During execution Gradle records results into an internal **binary** result store (historically under `build/test-results/<taskName>/binary/`). Both the HTML report and the JUnit-XML are *derived* from that binary data. That's why disabling one rendering doesn't affect the other, and why aggregation tooling can recombine binary results from several tasks. ## Quick mental map ``` build/ reports/tests/test/index.html <- open this in a browser (humans) test-results/test/TEST-*.xml <- parse this in CI (machines) ``` Knowing both paths is the baseline: you point your eyes at the HTML and point your CI at the XML.

  • If you have a custom `integrationTest` task, where do its reports go?
    `build/reports/tests/integrationTest/` (HTML) and `build/test-results/integrationTest/` (XML) — directories are keyed by task name, so no collision with `test`.
  • Why are there two different top-level dirs, `reports` and `test-results`?
    `build/reports/` holds rendered, human-facing reports; `build/test-results/` holds raw machine data (XML + binary). The HTML is generated from the binary results.

saying these in an interview costs you the question

  • Saying the HTML report lives under build/test-results (it's under build/reports/tests)
  • Claiming there is a single shared report dir for all test tasks

context

open as a page

How do you configure the test reports on a `Test` task — for example disable the HTML report on CI, keep the JUnit-XML, and move the XML to a custom directory?

level: middleimportance: must knowfreq 55%

basics

~10 s

Use the reports {} block on the test task: set html.required = false, junitXml.required = true, and point junitXml.outputLocation at the directory you want.

open as a page

Your CI shows green even when tests fail to compile or the build crashes before tests run. How should CI consume Gradle's JUnit-XML so test results are surfaced correctly?

level: seniorimportance: must knowfreq 48%

basics

~10 s

Point the CI test-reporter at **/build/test-results/test/*.xml, upload it as an artifact, and make sure the publish step runs even when the Gradle step fails (e.g. if: always()) so failures and crashes are still reflected.

open as a page

A developer complains that test `println`/log output 'disappears' and isn't shown on the console. Where does Gradle put that output by default, and how do the reports relate to it?

level: middleimportance: should knowfreq 34%

basics

~20 s

By default Gradle captures each test's stdout/stderr and folds it into the test reports (HTML page per class and, optionally, the JUnit-XML) instead of streaming it to the console. Open the HTML report to see it, or enable testLogging.showStandardStreams.

open as a page

Explain how Gradle's HTML test report relates to the binary test results, and why you can regenerate the HTML without re-running the tests.

level: seniorimportance: should knowfreq 30%

basics

~20 s

Gradle records raw results into a binary result store during the test run; both the HTML report and the JUnit-XML are rendered from that binary data, so the HTML is a derived view, not the primary record.

open as a page