Coverage on dependencies is not visible in Sonarqube

Hi,

I’ve read a lot of threads about multi-module projects and code coverage but I think I’m not in this situation and I’m really stuck.

I have an independent maven project containing some tests classes which test classes that are not in that project at all. They are just defined as dependencies in the project pom.

To include coverage of those classes in the jacoco report I’m using the property “jacoco.includes”.
It works perfectly and the jacoco report show me the coverage on those classes.
The report jacoco.xml also contain this coverage.

Now, when I’m importing this jacoco.xml file in sonar (with SonarScanner for Maven, the debug log indicate that my xml file is read correctly), Sonarqube server only show me the coverage on the classes in the test project. I don’t understand why it does not import all the informations contained in the jacoco.xml file ?

Clément.

EDIT :
Sonarqube server version : 7.7
Sonarqube scanner version : 3.6.0.1398
Jacoco maven plugin : 0.8.4

Hi,

I’m a little confused. From what I understand you have two separate projects, one with tests and the other with source files.

You import the JaCoCo report in your analysis of the source file project and the coverage is shown correctly…?
And some other part is missing…?

 
Ann

Hi,

Sorry if i was not clear in my first post. I’ll try to better explain my case.

I have two separate maven projects :

  • projectA
    • src/main/java/com/mycompany/classA
    • pom.xml
  • projectB
    • src/main/java/com/mycompany/classB
    • src/test/java/com/mycompany/classATest
    • src/test/java/com/mycompany/classBTest
    • pom.xml <- dependency on projectA

Jacoco maven plugin in projectB is configured with option <jacoco.includes>projectA</jacoco.includes>.
The jacoco report of projectB show coverage on classA and classB correctly.
But, when I’m running sonarscanner on projectB, sonarqube only show me coverage on classB.

What happens when you run the analysis of projectA with the same report? I am not familiar with “jacoco.includes” option, can you share relevant part of your pom.xml?

Hi !

Ok, the build configuration of project B was more tricky than I though before. The property “jacoco.includes” is not what I understood.
I’ll try to explain how it works.

Take the projectA et projectB as described in my previous post.

  • projectA generate a jar with compiled classes and a jar with sources
  • projectB :
    • have a dependency on jar with classes and jar with sources
    • jar with classes is unpacked in target/classes directory
    • jar with sources is unpacked in target/generated-sources/jacoco
    • the jacoco.includes (renamed “my.includes” in the sample) property is used by the two previous step to defined which dependencies will be unpacked…
    • the path target/generated-sources/jacoco is added to the source paths to be available during jacoco analysis

So, for Jacoco, it’s just like sources and classes of projectA is part of projectB…
Don’t know how sonar could handle that.

@saberduck : to answer your question, if I run scanner over projectA with report of projectB, the coverage is correctly reported over classes of projectA. So informations of coverage on thoses classes is really available in the report.

Here is the content of the two pom.xml

projectA :

<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/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mycompany.test</groupId>
	<artifactId>coverage-test-A</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-source-plugin</artifactId>
				<executions>
					<execution>
						<id>attach-sources</id>
						<goals>
							<goal>jar</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.jacoco</groupId>
				<artifactId>jacoco-maven-plugin</artifactId>
				<version>0.8.4</version>
				<executions>
					<execution>
						<id>jacoco-prepare-agent</id>
						<phase>process-test-classes</phase>
						<goals>
							<goal>prepare-agent</goal>
						</goals>
						<configuration>
							<propertyName>coverageAgent</propertyName>
							<excludes>
								<exclude>${jacoco.excludes}</exclude>
							</excludes>
						</configuration>
					</execution>
                    <execution>
                        <id>report</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

projectB :

<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/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mycompany.test</groupId>
	<artifactId>coverage-test-B</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<my.includes>coverage-test-A</my.includes>
		<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.mycompany.test</groupId>
			<artifactId>coverage-test-A</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>com.mycompany.test</groupId>
			<artifactId>coverage-test-A</artifactId>
			<version>0.0.1-SNAPSHOT</version>
			<classifier>sources</classifier>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.8.2</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
 			<plugin>
				<artifactId>maven-dependency-plugin</artifactId>
				<executions>
                    <!-- Extract client classes for jacoco coverage -->
                    <execution>
                        <id>unpack-jacoco-client-classes</id>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>unpack-dependencies</goal>
                        </goals>
                        <configuration>
                            <overWrite>true</overWrite>
                            <outputDirectory>${project.build.directory}/classes</outputDirectory>
                            <includeArtifactIds>${my.includes}</includeArtifactIds>
                            <includeType>jar</includeType>
                            <excludeClassifiers>tests,sources</excludeClassifiers>
                        </configuration>
                    </execution>
                    <!-- Extract client sources for jacoco coverage -->
                    <execution>
                        <id>unpack-jacoco-client-sources</id>
                        <phase>process-test-sources</phase>
                        <goals>
                            <goal>unpack-dependencies</goal>
                        </goals>
                        <configuration>
                            <overWrite>true</overWrite>
                            <outputDirectory>${project.build.directory}/generated-sources/jacoco</outputDirectory>
                            <includeArtifactIds>${my.includes}</includeArtifactIds>
                            <includeClassifiers>sources</includeClassifiers>
                        </configuration>
                    </execution>
				</executions>
			</plugin>
           <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.7</version>
                <executions>
                   <execution>
                       <id>add-source</id>
                       <phase>process-test-sources</phase>
                       <goals>
                          <goal>add-source</goal>
                       </goals>
                       <configuration>
                          <encoding>UTF-8</encoding>
                          <sources>
                             <source>${project.build.directory}/generated-sources/jacoco</source>
                          </sources>                   
                       </configuration>
                    </execution>
                </executions>
            </plugin>
                    
			<!-- add jacoco agent during integration-tests -->
			<plugin>
				<artifactId>maven-failsafe-plugin</artifactId>
				<version>2.22.2</version>
				<configuration>
					<argLine>-Xmx256m ${coverageAgent}</argLine>
					<reportsDirectory>${basedir}/target/surefire-reports</reportsDirectory>
					<includes>
						<include>**/*Test.java</include>
					</includes>
				</configuration>
				<executions>
					<execution>
						<id>test-delegate</id>
						<phase>integration-test</phase>
						<goals>
							<goal>integration-test</goal>
						</goals>
					</execution>
					<execution>
						<id>verify</id>
						<goals>
							<goal>verify</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

			<plugin>
				<groupId>org.jacoco</groupId>
				<artifactId>jacoco-maven-plugin</artifactId>
				<version>0.8.4</version>
				<executions>
					<execution>
						<id>jacoco-prepare-agent</id>
						<phase>process-test-classes</phase>
						<goals>
							<goal>prepare-agent</goal>
						</goals>
						<configuration>
							<propertyName>coverageAgent</propertyName>
							<excludes>
								<exclude>${jacoco.excludes}</exclude>
							</excludes>
						</configuration>
					</execution>
                    <execution>
                        <id>report</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

hello @honorec,

indeed, this will not show the coverage, because we exclude coverage for generated sources. There was recently a request to change this behavior, however I find this rather unusual, to measure coverage on generated code, if you think this is relevant, you can add vote here

https://community.sonarsource.com/t/code-coverage-is-calculated-wrong-with-default-maven-sources/12014/4

Also for your setup I think it would be better to analyze project A as another project in SQ with it’s own coverage report imported.

Hi @saberduck ,

thanks for the tip. The solution suggested in the link is enough for me, I will just add manually the path with the sources to analyze with the sonar.sources property. It will do the trick :slight_smile: