skip to content

Test Report Aggregation

The test-report-aggregation plugin for merging results from many subprojects into a single report. Interviewers ask because per-module reports become unusable once a build has twenty modules.

on this pageshow

questions

5

What is the `test-report-aggregation` plugin in Gradle and what problem does it solve in a multi-project build?

level: juniorimportance: must knowfreq 55%

answer

  1. core plugin, no version
  2. one HTML report from many subprojects
  3. testAggregateTestReport task
  4. testReportAggregation configuration
  5. variant-aware, not file paths

basics

~10 s

It's a core Gradle plugin that merges the test results of multiple subprojects into a single combined HTML report, so you don't have to open each subproject's report separately.

solid answer

~40 s

`test-report-aggregation` is a built-in Gradle plugin (no external dependency) that collects the test results produced across many subprojects and renders one consolidated HTML report. In a multi-project build, each subproject normally produces its own `build/reports/tests/test/index.html`; reviewing them one by one is tedious and gives no project-wide pass/fail view. You apply the plugin (usually on an aggregating project such as a dedicated `test-report` project or the application project), it adds a `testAggregateTestReport` task, and running it gathers the binary test result data from every project it depends on and writes a single HTML report under `build/reports/tests/...`. It uses variant-aware dependency resolution to find result data, so it only needs project dependencies declared, not manual wiring of file paths.

code

kotlin · 10 lines
kotlin
plugins {
    id("test-report-aggregation")
}

dependencies {
    testReportAggregation(project(":service-a"))
    testReportAggregation(project(":service-b"))
}

// Run: ./gradlew testAggregateTestReport

go deeper

for a junior

Know it produces one combined test report across subprojects and adds a testAggregateTestReport task.

for a middle

Explain it merges binary result data via project dependencies on a testReportAggregation configuration, not file copying.

for a senior

Discuss applying it on a dedicated aggregation project and how variant-aware resolution supplies the result data.

for a principal

Position it within a standardized multi-project reporting strategy alongside jacoco-report-aggregation and a CI artifact convention across teams.

## The problem In a Gradle multi-project build, every project that runs tests produces its own report. By default `Test` tasks write: - Binary result data to `build/test-results/test/` (used by tooling) - A human HTML report to `build/reports/tests/test/index.html` With ten subprojects you get ten separate HTML reports and no single "did everything pass?" view. CI dashboards and humans both want one artifact. ## What the plugin does The **`test-report-aggregation`** plugin is a *core* Gradle plugin (ships with the distribution — no `dependencies {}` entry, no version). Applying it: 1. Adds a resolvable configuration that knows how to ask other projects for their *test result data* (not their HTML — the raw binary results). 2. Registers a task named **`testAggregateTestReport`** of type `AggregateTestReport`. 3. Wires that task to merge the collected binary results into ONE HTML report, typically at `build/reports/tests/unit-test/aggregated-results/index.html`. ## How it finds the data It relies on **variant-aware resolution**. You declare ordinary project dependencies, and the plugin requests the `test-results` outgoing variant from each. This is why you don't hand-wire file paths — Gradle's dependency graph carries the result data via attributes. ```kotlin plugins { id("test-report-aggregation") } dependencies { testReportAggregation(project(":service-a")) testReportAggregation(project(":service-b")) } reporting { reports { val testAggregateTestReport by getting(AggregateTestReport::class) { testSuiteName = "test" } } } ``` Run `./gradlew testAggregateTestReport` and you get one combined report. ## Where to apply it A common pattern is a dedicated project (e.g. `:test-report`) that depends on all the others purely to aggregate. The `jvm-test-suite` and `java` plugins also integrate so the `application` or `java` plugin's project can host the aggregation. The sibling **`jacoco-report-aggregation`** plugin does the same idea for coverage.

  • Is `test-report-aggregation` a third-party plugin you add a version for?
    No. It is a core Gradle plugin bundled with the distribution, so you apply it by id with no version and no buildscript dependency.
  • What task name does it add?
    `testAggregateTestReport` (of type `AggregateTestReport`), which produces the merged HTML report.

Like a teacher collecting every student's individual quiz sheet and stapling them into one gradebook instead of leaving ten loose papers on the desk.

saying these in an interview costs you the question

  • Saying you must manually copy each subproject's HTML into one folder — the plugin merges binary result data, not HTML.
  • Treating it as a community plugin that needs a version number.

context

open as a page

How do you set up test report aggregation across several subprojects? Walk through applying the plugin and declaring what gets aggregated.

level: middleimportance: must knowfreq 50%

basics

~10 s

Apply test-report-aggregation on an aggregating project, add each subproject via the testReportAggregation dependency configuration, then run testAggregateTestReport to get one merged HTML report.

open as a page

Why does test report aggregation merge binary result data rather than the generated HTML reports, and what attribute/variant mechanism makes that work?

level: seniorimportance: should knowfreq 35%

basics

~20 s

HTML is already-rendered output that can't be cleanly merged. Gradle instead collects each project's raw binary test results via a dedicated outgoing variant selected by attributes, then renders one fresh report from all of them.

open as a page

When you run `testAggregateTestReport` in CI and some subproject tests fail, what happens to the report and the build, and how do you make the report reliably available?

level: seniorimportance: should knowfreq 30%

basics

~10 s

A failing test fails its Test task, which can stop the build before aggregation runs. Use --continue (or finalizers) so all tests run and the aggregate report is still produced even when something fails.

open as a page

How would you architect cross-project reporting so that unit and integration test suites each get their own aggregated report, and how does this relate to coverage aggregation?

level: principalimportance: nice to knowfreq 18%

basics

~10 s

Model each suite with jvm-test-suite, then register one AggregateTestReport per suite name (e.g. test and integrationTest). For coverage, apply the sibling jacoco-report-aggregation plugin, which works the same way for JaCoCo data.

open as a page