skip to content

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