From 7af501d8ecbfb276c8378100bec800fccbe332c9 Mon Sep 17 00:00:00 2001 From: mali Date: Thu, 20 Oct 2022 16:44:28 +0000 Subject: [PATCH] SQ 9.7 --- README.md | 97 +++++++++++++++++++ module1/pom.xml | 16 +++ .../main/java/com/acme/module1/Module1.java | 17 ++++ .../java/com/acme/module1/Module1Test.java | 12 +++ module2/pom.xml | 16 +++ .../main/java/com/acme/module2/Module2.java | 16 +++ .../java/com/acme/module2/Module2Test.java | 11 +++ pom.xml | 87 +++++++++++++++++ tests/pom.xml | 47 +++++++++ .../test/java/com/acme/its/ModulesTest.java | 19 ++++ 10 files changed, 338 insertions(+) create mode 100644 README.md create mode 100644 module1/pom.xml create mode 100644 module1/src/main/java/com/acme/module1/Module1.java create mode 100644 module1/src/test/java/com/acme/module1/Module1Test.java create mode 100644 module2/pom.xml create mode 100644 module2/src/main/java/com/acme/module2/Module2.java create mode 100644 module2/src/test/java/com/acme/module2/Module2Test.java create mode 100644 pom.xml create mode 100644 tests/pom.xml create mode 100644 tests/src/test/java/com/acme/its/ModulesTest.java diff --git a/README.md b/README.md new file mode 100644 index 0000000..669d37b --- /dev/null +++ b/README.md @@ -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 `` 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 + + + + + org.jacoco + jacoco-maven-plugin + + + + prepare-agent + + + + + + + +``` + +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 + + + + org.jacoco + jacoco-maven-plugin + + + report + + report-aggregate + + verify + + + + + +``` + +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 + + ${maven.multiModuleProjectDirectory}/tests/target/site/jacoco-aggregate/jacoco.xml + +``` + +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/) diff --git a/module1/pom.xml b/module1/pom.xml new file mode 100644 index 0000000..77ef6f2 --- /dev/null +++ b/module1/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + + org.sonarqube + sonarscanner-maven-aggregate + 1.0-SNAPSHOT + + + module1 + + Module 1 + + diff --git a/module1/src/main/java/com/acme/module1/Module1.java b/module1/src/main/java/com/acme/module1/Module1.java new file mode 100644 index 0000000..906c68f --- /dev/null +++ b/module1/src/main/java/com/acme/module1/Module1.java @@ -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"); + } + +} diff --git a/module1/src/test/java/com/acme/module1/Module1Test.java b/module1/src/test/java/com/acme/module1/Module1Test.java new file mode 100644 index 0000000..b840561 --- /dev/null +++ b/module1/src/test/java/com/acme/module1/Module1Test.java @@ -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(); + } +} diff --git a/module2/pom.xml b/module2/pom.xml new file mode 100644 index 0000000..b9c5f76 --- /dev/null +++ b/module2/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + + org.sonarqube + sonarscanner-maven-aggregate + 1.0-SNAPSHOT + + + module2 + + Module 2 + + diff --git a/module2/src/main/java/com/acme/module2/Module2.java b/module2/src/main/java/com/acme/module2/Module2.java new file mode 100644 index 0000000..8113f3f --- /dev/null +++ b/module2/src/main/java/com/acme/module2/Module2.java @@ -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"); + } +} diff --git a/module2/src/test/java/com/acme/module2/Module2Test.java b/module2/src/test/java/com/acme/module2/Module2Test.java new file mode 100644 index 0000000..2fa2008 --- /dev/null +++ b/module2/src/test/java/com/acme/module2/Module2Test.java @@ -0,0 +1,11 @@ +package com.acme.module2; + +import org.junit.Test; + +public class Module2Test { + + @Test + public void coveredByUnitTest() { + new Module2().coveredByUnitTest(); + } +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..bbed4ed --- /dev/null +++ b/pom.xml @@ -0,0 +1,87 @@ + + + 4.0.0 + + org.sonarqube + sonarscanner-maven-aggregate + 1.0-SNAPSHOT + pom + + Example of multi-module Maven project + + + module1 + module2 + tests + + + + UTF-8 + UTF-8 + 1.8 + 1.8 + ${maven.multiModuleProjectDirectory}/tests/target/site/jacoco-aggregate/jacoco.xml + + + + + com.google.guava + guava + 29.0-jre + + + junit + junit + 4.13.1 + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + + org.sonarsource.scanner.maven + sonar-maven-plugin + 3.7.0.1746 + + + org.jacoco + jacoco-maven-plugin + 0.8.6 + + + + + + + + coverage + + true + + + + + org.jacoco + jacoco-maven-plugin + + + prepare-agent + + prepare-agent + + + + + + + + + diff --git a/tests/pom.xml b/tests/pom.xml new file mode 100644 index 0000000..b7b7cad --- /dev/null +++ b/tests/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + + org.sonarqube + sonarscanner-maven-aggregate + 1.0-SNAPSHOT + + + tests + + Tests + + + + org.sonarqube + module1 + 1.0-SNAPSHOT + + + org.sonarqube + module2 + 1.0-SNAPSHOT + + + + + + + org.jacoco + jacoco-maven-plugin + + + report + + report-aggregate + + verify + + + + + + + diff --git a/tests/src/test/java/com/acme/its/ModulesTest.java b/tests/src/test/java/com/acme/its/ModulesTest.java new file mode 100644 index 0000000..5c12a20 --- /dev/null +++ b/tests/src/test/java/com/acme/its/ModulesTest.java @@ -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(); + } + +}