This blog post goes over some recipes for adding code coverage report to Maven-based projects with Jacoco.
Standard usage
Based on offical instruction and this, you need to add the following code snippet in to your Maven pom.xml
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
At least, you need “prepare-agent” before test phase for Jacoco instrumentation and “report” after test phase for generating the report. You could subject the project to code coverage and generate the same report without making any changes to the pom file. To do this, run the following command:
1
|
|
You may get the following error:
1
|
|
There are two options to fix that error.
The easiest way is to specify the groupId
and artifactId
parameters of the plugin explicitly.
You can also add version
to ensure the stability of your build pipeline.
1
|
|
The more long-term solution is to add the following in to your Maven “settings.xml”.
1 2 3 |
|
Tests with Mock
If mocking is involved in unit tests, you need to use “instrument” and “restore-instrumented” steps.
Reference:
Multi-module Maven projects
Officially, multi-module Maven projects are supported differently by Jacoco as documented here. Instrumentation will be similar but the challenge of multi-module Maven projects lies in how to collect and report code coverage of all modules correctly. Jacoco Maven standard goals, as shown in sections above, 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.
In the past, there are some ad-hoc solutions such as this (for Jacoco 0.5.x) to work around that limit. However, those patterns are also error-prone and hard to customize, especially when Jacoco is used with Surefire plugin. Fortunately, Jacoco recently introduced a new Maven goal “report-aggregate” in its release 0.7.7 which will aggregate code coverage data across Maven modules. Its usage is also present in the same link (quoted below) but it is too succint and not very helpful for new users.
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.
Let' say you have a multi-module Maven project with this structure:
1 2 3 4 |
|
To use Jacoco “report-aggregate” goal for these modules, you first need to add a dedicated “coverage” module. This “coverage” module should be added into the root POM. The multi-module Maven project should now look like this:
1 2 3 4 5 |
|
The POMs for each module does not need to change at all. The POM for the “coverage” module will look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
|
Note that we still require “prepare-agent” step to run before the first test suite. Depending on what plugins are being used and how the modules are organized within the project, we might have different setup for that particular step. One option is to run from the command-line:
1 2 3 4 5 |
|
Links:
Customizations
In theory, a global threshold can be defined in coverage/pom.xml
to enforce code coverage standard across teams.
However, in practice, different teams are at different stages of module/service maturity and blindly having a global threshold will hamper teams working on newer services/modules.
In addition, it does not make sense to enforce code coverage on some Maven modules such as those generated in GRPC.
In Jacoco, you can set different coverage limits for individual modules instead of a global threshold for all modules. In the following example, you can specify a coverage threshold for module A by modifying module A’s pom.xml file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
|
As you can see, you can also specify files being excluded from coverage calculation.
References
- Jacoco Maven plugin: there are example POMs.