5

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?

nishant
  • 955
  • 2
  • 11
  • 27
  • Unit tests are by definition local to the appropriate module and not extracted to a separte module. So your setup for a separate unit tests module does not make sense. The intention in Maven is having the production code plus the appropriate unit tests within the same module. As the folder structure shows `src/main/java` production code. `src/test/java` unit test code. – khmarbaise Nov 13 '14 at 13:28
  • I think this is a valid setup if you consider the tests module as a location for integration tests. For now it seems that jacoco doesn't support this, you can try Sonar if you are in the mood to really do this. Otherwise, wait for the next version of Jacoco, it might actually support it :D (https://github.com/jacoco/jacoco/pull/97) – AMilassin Nov 13 '14 at 13:39
  • If we are talking about integration tests yes but this is not written in the question. – khmarbaise Nov 13 '14 at 13:40
  • If you like to run integration tests with jacoco you need an agent which must be configured in maven-failsafe-plugin (if we are talking about integration tests) appropriatley. See here: http://www.petrikainulainen.net/programming/maven/creating-code-coverage-reports-for-unit-and-integration-tests-with-the-jacoco-maven-plugin/ – khmarbaise Nov 13 '14 at 13:42
  • 1
    Possible duplicate of [How to configure multi-module Maven + Sonar + JaCoCo to give merged coverage report?](http://stackoverflow.com/questions/13031219/how-to-configure-multi-module-maven-sonar-jacoco-to-give-merged-coverage-rep) – Stewart Feb 02 '17 at 19:21

3 Answers3

6

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.

Sven Oppermann
  • 321
  • 4
  • 9
0

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.

mystarrocks
  • 4,040
  • 2
  • 36
  • 61
0

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.

Jess Chen
  • 3,136
  • 1
  • 26
  • 35