Maven multi module project with separate tests module - Code Coverage?

3.7k views Asked by At

I have a maven multi module project.

root:
    moduleA/   # no unit tests
    moduleB/   # no unit tests
    moduleC/   # no unit tests
    tests/     # All unit tests, since depends on modules A, B and C

All tests are in single module called tests/ and all code is in separate modules.

Is there a way I can get code coverage?

3

There are 3 answers

1
mystarrocks On

I don't think either of jacoco or cobertura is capable of reporting code coverage across modules. You may want to try instrumenting the compiled classes before running the test coverage report rather than relying on on-the-fly instrumentation.

See this jacoco maven goal to perform the offline instrumentation.

0
Sven Oppermann On

There is a way to accomplish this. The magic is to create a combined jacoco.exec file and to do it in two steps. My pom:

<properties>
    ...
    <jacoco.overall.exec>${maven.multiModuleProjectDirectory}/target/jacoco_analysis/jacoco.exec</jacoco.overall.exec>
</properties>

<build>
    <pluginManagement>
        <plugins>

            ...

            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.7.8</version>
                <configuration>
                    <destFile>${jacoco.overall.exec}</destFile>
                    <dataFile>${jacoco.overall.exec}</dataFile>
                </configuration>
            </plugin>

            ...

        </plugins>
    </pluginManagement>
</build>

<profiles>
    <profile>
        <id>runTestWithJacoco</id>
        <activation>
            <property>
                <name>runTestWithJacoco</name>
                <value>true</value>
            </property>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>default-prepare-agent</id>
                            <goals>
                                <goal>prepare-agent</goal>
                            </goals>
                            <configuration>
                                <append>true</append>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
    <profile>
        <id>createJacocoReport</id>
        <activation>
            <property>
                <name>createJacocoReport</name>
                <value>true</value>
            </property>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>default-report</id>
                            <phase>validate</phase>
                            <goals>
                                <goal>report</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

Add this to your parent pom and execute mvn clean install -DrunTestWithJacoco and than mvn validate -DcreateJacocoReport. Now you have the complete coverage of a class and it doesn't matter which test covered it. The magic is to use maven.multiModuleProjectDirectory to create a combined jacoco.exec file. This property is available since maven 3.3.1 and points to the folder where you started your maven build.

0
Jess Chen On

Since Jacoco version: 0.7.7, you can use report-aggregate.

Root pom.xml :

<project>
[...]
  <build>
    <plugins>
     <!--   refer:https://prismoskills.appspot.com/lessons/Maven/Chapter_06_-_Jacoco_report_aggregation.jsp     -->
    <plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.6</version>
    <executions>
        <execution>
            <id>prepare-agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>

        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
                <goal>report-aggregate</goal>
            </goals>
        </execution>
    </executions>
    </plugin>
    <plugins>
  </build>
[...]
<pluginManagement>
  <plugins>
    <!--    unit test plugin        -->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
      <version>3.0.0-M5</version>
      <dependencies>
        <dependency>
          <groupId>org.apache.maven.surefire</groupId>
          <artifactId>surefire-junit47</artifactId>
          <version>3.0.0-M5</version>
        </dependency>
      </dependencies>
      <configuration>
        <argLine>${argLine} -Dfile.encoding=UTF-8</argLine>
      </configuration>
    </plugin>
  </plugins>
</pluginManagement>
[...]
</project>

Sub-modules pom.xml:

<project>
[...]
<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
            <includes>
                <include>[path]</include>
            </includes>
        </configuration>
    </plugin>
</plugins>
[...]
</project>

If you use Jenkin, you can just use jacoco plugin and <goal>report</goal> without other new things.