1

I have a project that uses SonarQube to analyse my code. As the title suggests, the coverage metric is always appears to be 0 in the SQ report (on my server) despite me having multiple Junit tests. I currently run the following command

clean package deploy sonar:sonar -Dsonar.projectKey=SomeName -Dmaven.test.skip=true

when building my project in Jenkins (Jenkins Maven project).

I had similar issue some time back with different project. I manage to resolved it via this article. However, it didn't help this time. After searching for a bit, I found article 1 and article 2 (as well as some more with similar ideas). Both had some good suggestions but unfortunately nothing worked.

I noticed that I also get the following warning every time (don't know what causes it)

Cobertura report not found at /var/lib/jenkins/jobs/SomeProjectName/workspace/SomeFolderName/target/site/cobertura/coverage.xml

At first, I tried to add cobertura plugin (as suggested here) but that just removed the warning (coverage remained 0 in the report). My current understanding is that it overwrites Jacoco but I failed to find the reason why or solution to it.

My plugins:

<build>
        <plugins>
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>scala-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>scala-compile-first</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>add-source</goal>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>scala-test-compile</id>
                        <phase>process-test-resources</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <verbose>true</verbose>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <finalName>uber-${project.artifactId}-${project.version}</finalName>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>META-INF/*.SF</exclude>
                                <exclude>META-INF/*.DSA</exclude>
                                <exclude>META-INF/*.RSA</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.5</version>
                <executions>
                    <execution>
                        <id>pre-unit-test</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
                            <propertyName>surefireArgLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>post-unit-test</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                        <configuration>
                            <dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
                            <outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
                        </configuration>
                    </execution>
                    <execution>
                        <id>pre-integration-test</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
                            <propertyName>failsafeArgLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>post-integration-test</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                        <configuration>
                            <dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>
                            <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.avro</groupId>
                <artifactId>avro-maven-plugin</artifactId>
                <version>1.9.2</version>
                <executions>
                    <execution>
                        <configuration>
                            <outputDirectory>${project.basedir}/target/generated-sources</outputDirectory>
                            <sourceDirectory>${project.basedir}/src/main/resources/</sourceDirectory>
                        </configuration>
                        <goals>
                            <goal>schema</goal>
                            <goal>protocol</goal>
                            <goal>idl-protocol</goal>
                        </goals>
                        <id>schemas</id>
                        <phase>generate-sources</phase>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

My properties:

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>11</java.version>
    </properties>
Joe
  • 337
  • 6
  • 21
  • 1
    Pretty sure @david-m-karr has sound advice, but most basicly, you must execute the unit tests (with jacoco instrumentaion configured properly) in order to determine the coverage.SonarQube juat repotts on what jacoco measured. As long as you have `-Dmaven.test.skip=true`, you'll get a zero. – Ian W Feb 06 '21 at 02:49
  • @IanW Hey! Good point, that makes more sense now that I removed test skips. Thanks! – Joe Feb 08 '21 at 17:22

2 Answers2

1

There are a few things that have to be set correctly to result in your test coverage being shown in SonarQube. Some of these settings have defaults that may work, but I try to avoid magic defaults, in favor of ensuring that my settings agree with each other.

Surefire and Jacoco have to have settings that agree with each other, and SonarQube has to know where to find the coverage data file.

I'm going to suggest some property values for you to use.

sonar.coverage.jacoco.xmlReportPaths: ${basedir}/target/jacoco_report/jacoco.xml
jacoco.path: ${basedir}/target/jacoco_report

Then, here is an excerpt for your jacoco plugin:

<!-- Prepares the property pointing to the JaCoCo runtime agent which 
    is passed as VM argument when Maven the Surefire plugin is executed. -->
<execution>
    <id>pre-unit-test</id>
    <goals>
        <goal>prepare-agent</goal>
    </goals>
    <configuration>
        <propertyName>surefireArgLine</propertyName>
    </configuration>
</execution>
<!-- Ensures that the code coverage report for unit tests is created 
    after unit tests have been run. -->
<execution>
    <id>post-unit-test</id>
    <phase>test</phase>
    <goals>
        <goal>report</goal>
    </goals>
    <configuration>
        <!-- Sets the output directory for the code coverage report. -->
        <outputDirectory>${jacoco.path}</outputDirectory>
    </configuration>
</execution>

Finally, this goes in the configuration block of the Surefire plugin:

<!-- Sets the VM argument line used when unit tests are run. -->
<argLine>${surefireArgLine}</argLine>

However, in your case you have a very high-level issue that would result in zero coverage even if you had all of these settings done correctly. Thanks to @Ian W for pointing this out.

When I saw you write "despite me having multiple Junit tests", I took your word for it that you're actually executing the unit tests. You have "-Dmaven.test.skip=true" on your command line, which causes it to not execute any unit tests. Remove that.

David M. Karr
  • 14,317
  • 20
  • 94
  • 199
  • Thanks for the response! Unfortunetly, I cannot add ```${surefireArgLine}``` to my surefire plugin: it says that symbol is unrecognised (both names in jacoco plugin and surefire plugin are the same so not a typo). – Joe Feb 08 '21 at 17:21
  • You'd have to update your post with actual details for us to tell what you did wrong here. – David M. Karr Feb 08 '21 at 17:33
  • Most basicly, you must execute the unit tests (with jacoco instrumentaion configured properly) in order to determine the coverage.SonarQube just reports on what jacoco measured. As long as you have `-Dmaven.test.skip=true`, you'll get a zero. @david-m-karr, pls add that to your response. – Ian W Feb 08 '21 at 21:29
1

I am using java 11 with maven version 3.8.3 configured with jacoco 0.8.3 plugin. the Code coverage is operational. SonadeQuebe dont't dispaly 0%

command: mvn sonar:sonar -Dsonar.projectKey=diag -Dsonar.host.url=http://sonar.XXXXX/sonar -Dsonar.login=xxxx -Dsonar.password=xxxxx

In pom.xml

<properties>
    <java.version>11</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <jacoco-maven-plugin.version>0.8.3</jacoco-maven-plugin.version>
    <sonar-maven-plugin.version>3.4.0.905</sonar-maven-plugin.version>
    <sonar.java.codeCoveragePlugin>jacoco</sonar.java.codeCoveragePlugin>
    <sonar.tests>${project.basedir}/src/test/</sonar.tests>
    ...
<plugins>
    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>${jacoco-maven-plugin.version}</version>
        <executions>
            <execution>
                <goals>
                    <goal>prepare-agent</goal>
                </goals>
            </execution>
            <execution>
                <id>report</id>
                <phase>prepare-package</phase>
                <goals>
                    <goal>report</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
Soufiane D
  • 21
  • 3