Skip to content

MavenMultiModule

Evgeny Mandrikov edited this page Jul 12, 2017 · 25 revisions

Maven Multi-Module Builds

Support for Maven multi-module build was a long outstanding feature request for JaCoCo. This page tries to collect all information about the history of this feature.

Problem statement

JaCoCo Maven goals used to work on single modules only: Tests are executed within the module and contributed coverage only to code within the same module. Coverage reports were created for each module separately. There was no built-in support for cross-module coverage or combined reports for multiple modules.

Current status

JaCoCo version 0.7.7 implemented a new maven goal jacoco:report-aggregate. This report aggregates coverage data across Maven modules.

Usage

Create a dedicated module in your project for generation of the report. This module should depend on all or some other modules in the project. JaCoCo itself does this in the org.jacoco.doc module (see the pom.xml).

Implementation history

Related Feature Requests

Work-Arounds

  • The JaCoCo Ant report task allows to specify arbitrary exec file, class file and source file locations. This task can be embedded with the maven-antrun-plugin.
  • Use external tools for report generation like SonarQube.

Use Cases

There is a couple of use cases where code coverage needs to be determined across multiple modules:

  • Creation of structured, browseable report for multiple modules.
  • A report which shows the overall coverage figures (also check goals for overall coverage)
  • Tests are located in a module separate from the code under test (e.g. Eclipse/Tycho). In this case the execution data is created within another module than the code under test.
  • Integration tests might contribute code coverage to multiple modules.

More Aspects:

  • Separate vs. combined reports for different test test levels (unit, it)
  • Transitive coverage (e.g. test for A causes code coverage on B when A depends on B): this might be desirable or not

Implementation Options

Maven seems to have no concept to define when build artifacts of a module are processed in a multi-module project. Every maven project passes all lifecycle phases before the next project is built. In multi-module projects this can be a problem if you want to aggregate build artifacts of subprojects after they are created. In theory this leaves us with the following three strategies:

Strategy: Aggregator

An aggregator is a Maven project that contains other Maven projects as modules. Using an aggregator project seems to be the natural solution as this directly reflects the project hierarchy. Unfortunately this strategy comes with a number of drawbacks:

  • Aggregator goals are executed before its submodules, i.e., the build cannot create a combined coverage report in an aggregator as they have to be built and tested first.
  • Aggregator goals cannot be bound to a lifecycle phase, as they are executed before its submodules. They can be specified manually on the command line to create a combined coverage report.
  • There is very limited documentation for aggregators, some sources suggest that aggregators are deprecated and should not be used.

Strategy: Incremental Reporting

In theory combined coverage reports can be created a in aggregator project, if all its submodules would contribute to the report while they are built. Every module would collect its coverage data and augment the combined report “on-the-fly”. This would show correct data in the report even for partial builds, i.e., builds that failed at some point. An incremental strategy for reporting is, however, not easy to implement and would have a number of drawbacks:

  • Most importantly, incremental reporting with the current report generation is not thread-safe. An extra mechanism to update existing HTML reports (with structural navigation) would be needed.
  • An on-the-fly report generation is also expensive. It would have to manipulate existing files, and most likely increase build times.

Strategy: Module with Dependencies

The problems with aggregator projects can be solved with an extra "reporting" module. In a multi-module Maven project a separate module is defined that does not contribute actual content but creates a combined coverage report. It defines a dependency to all the modules that should be included in the combined report. The "reporting" module would be built after its dependencies and have access to the exec files as well as class and source files from projects it depends on. This strategy seems to work best with the current Maven architecture. From a user's perspective one could argue that such a separate module would bloat the build definition. Or, that the separate module cannot have any submodules from which it could consume exec or class files. However, compared to the other strategies these drawbacks seem rather minor and can be handled in a consistent manner.

Web Links

Implementation of Multi-Module Reports

TODO:

  • how to declare a reporting module
  • how to find build artifacts (exec, class, source files) from dependencies
  • how to generate a combined coverage report