This commit is contained in:
mali 2022-10-20 16:44:28 +00:00
commit 7af501d8ec
10 changed files with 338 additions and 0 deletions

97
README.md Normal file
View File

@ -0,0 +1,97 @@
# Multi-module Apache Maven example
This project imports JaCoCo's aggregate XML report to be able to report coverage across modules as well as unit test coverage inside the module.
For a basic example see [basic maven project](../maven-basic/README.md).
## Usage
* Build the project, execute all the tests and analyze the project with SonarQube Scanner for Maven:
```shell
mvn clean verify sonar:sonar
```
## Description
This project consists of 3 modules.
* [`module1`](module1/pom.xml) and [`module2`](module2/pom.xml) contain "business logic" and related unit tests.
* [`tests`](tests/pom.xml) module contains integration tests which test functionality using both modules.
`tests` module is also the one which creates the aggregate coverage report imported into SonarQube.
To generate the report we configure the JaCoCo plugin to attach its agent to the JVM which is executing the tests in the top level [pom](pom.xml).
This configuration is done in the `<pluginManagment>` section, so it will be applied on every submodule.
It is also configured inside the `coverage` profile, so this can be activated as needed (e.g. only in CI pipeline).
```xml
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
```
Once we have configured JaCoCo to collect coverage data, we need to generate the XML coverage report to be imported into SonarQube.
We will use [report-aggregate](https://www.jacoco.org/jacoco/trunk/doc/report-aggregate-mojo.html) goal which collects data from all modules dependent on the `tests` module.
To achieve this we configure the JaCoCo plugin by configuring execution of `report-aggregate` goal in `verify` phase.
See [pom.xml](tests/pom.xml)
```xml
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report</id>
<goals>
<goal>report-aggregate</goal>
</goals>
<phase>verify</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
```
This will create a report in `tests/target/site/jacoco-aggregate/jacoco.xml`. To import this report we will set
`sonar.coverage.jacoco.xmlReportPaths` property with the `${maven.multiModuleProjectDirectory}` so every module knows where the coverage should be imported from
```xml
<properties>
<sonar.coverage.jacoco.xmlReportPaths>${maven.multiModuleProjectDirectory}/tests/target/site/jacoco-aggregate/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
</properties>
```
Alternately we can set this property on the command line with the `-D` switch:
```shell
mvn -Dsonar.coverage.jacoco.xmlReportPaths=C:\projects\sonar-scanning-examples\sonarscanner-maven-aggregate\tests\target\site\jacoco-aggregate\jacoco.xml clean verify sonar:sonar
```
We have to use an absolute path, because the report will be imported for each module separately and the path is resolved relative to the module dir.
## Documentation
[SonarScanner for Maven](https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-maven/)

16
module1/pom.xml Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonarqube</groupId>
<artifactId>sonarscanner-maven-aggregate</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>module1</artifactId>
<name>Module 1</name>
</project>

View File

@ -0,0 +1,17 @@
package com.acme.module1;
public class Module1 {
public void coveredByUnitTest() {
System.out.println("This method is covered by unit test");
}
public void coveredByIntegrationTest() {
System.out.println("This method is covered by integration test");
}
public void uncovered() {
System.out.println("This method is not covered");
}
}

View File

@ -0,0 +1,12 @@
package com.acme.module1;
import org.junit.Test;
public class Module1Test {
@Test
public void coveredByUnitTest() {
Module1 module1 = new Module1();
module1.coveredByUnitTest();
}
}

16
module2/pom.xml Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonarqube</groupId>
<artifactId>sonarscanner-maven-aggregate</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>module2</artifactId>
<name>Module 2</name>
</project>

View File

@ -0,0 +1,16 @@
package com.acme.module2;
public class Module2 {
public void coveredByUnitTest() {
System.out.println("This method is covered by unit test");
}
public void coveredByIntegrationTest() {
System.out.println("This method is covered by integration test");
}
public void uncovered() {
System.out.println("This method is not covered");
}
}

View File

@ -0,0 +1,11 @@
package com.acme.module2;
import org.junit.Test;
public class Module2Test {
@Test
public void coveredByUnitTest() {
new Module2().coveredByUnitTest();
}
}

87
pom.xml Normal file
View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.sonarqube</groupId>
<artifactId>sonarscanner-maven-aggregate</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Example of multi-module Maven project</name>
<modules>
<module>module1</module>
<module>module2</module>
<module>tests</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<sonar.coverage.jacoco.xmlReportPaths>${maven.multiModuleProjectDirectory}/tests/target/site/jacoco-aggregate/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
</properties>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.7.0.1746</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.6</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<profiles>
<profile>
<id>coverage</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

47
tests/pom.xml Normal file
View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonarqube</groupId>
<artifactId>sonarscanner-maven-aggregate</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>tests</artifactId>
<name>Tests</name>
<dependencies>
<dependency>
<groupId>org.sonarqube</groupId>
<artifactId>module1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.sonarqube</groupId>
<artifactId>module2</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report</id>
<goals>
<goal>report-aggregate</goal>
</goals>
<phase>verify</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,19 @@
package com.acme.its;
import com.acme.module1.Module1;
import com.acme.module2.Module2;
import org.junit.Test;
public class ModulesTest {
@Test
public void integrationTest1() {
new Module1().coveredByIntegrationTest();
}
@Test
public void integrationTest2() {
new Module2().coveredByIntegrationTest();
}
}