2
votes

We're using maven to run a sonar analysis and it works well except for the code coverage results with jacoco. We have an eclipse project that uses tycho-surefire-plugin for testing. I've not overriden the argLines properties so solutions involving that line may not be appropiate.

Facts :

  • Maven structure structure:
    • parent
      • master
        • module 1
        • module ...
        • module n
  • Testing structure:
    • client.admin (eclipse-plugin packaging)
    • client.admin.test.fragment (eclipse-test-plugin packaging)
  • Properties that are correctly set and identified
    • sonar.junit.reportsPath
    • sonar.jacoco.reportPath,
    • sonar.jacoco.itReportPath
    • sonar.core.codeCoveragePlugin
    • sonar.language

The main problem is with the following properties

  • sonar.test
  • sonar.sources
  • sonar.java.binaries

As seen in the Testing structure in the client.admin.test.fragment tests are contained in the /src folder and the sources are located in the project client.admin in the /src folder too. When we run the analysis we get the following error :

[WARN] Coverage information was not collected. Perhaps you forget to include debug information into compiled classes?

I believe this has to do with the properties sonar.java.binaries that goes looking for the sources in target/classes of the fragment project (client.admin.project) that are in fact located in the host project (client.admin). In the fragment project we've configured sonar.tests and sonar.sources properties so that they call the /src folder of the corresponding projects.

In the sonar Analysis Parameters page there says that only sonar.sources is a maven valid property, sonar.tests and sonar.java.binaries cannot apparently be configured in maven. How then could I attach the binaries to the project. I've tried copying the folder target/classes from the host project but I got the same message. Is there any workaround in maven ?

Edit 1

There is one jacoco.exec file that is generated for the whole project that can be found at the parent folder. This was done configuring the jacoco.destFile and sonar.jacoco.reportPath properties

Jacoco plugin in main pom :

<!-- Jacoco Plugin -->
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>prepare-agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
            <configuration>
                <destFile>${sonar.jacoco.reportPath}</destFile>
                <append>true</append>
            </configuration>
        </execution>
        <execution>
            <id>default-report</id>
            <goals>
                <goal>report</goal>
            </goals>
            <configuration>
                <dataFile>${sonar.jacoco.reportPath}</dataFile>
                <outputDirectory>${jacoco.reports.outputDirectory}</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

Maven Plugin Versions:

  • sonar: 2.4
  • jacoco: 0.7.1.201405082137

Properties

<sonar.language>java</sonar.language>
<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
<sonar.junit.reportsPath>${project.build.directory}/surefire-reports/</sonar.junit.reportsPath>
<sonar.jacoco.reportPath>${basedir}/../../../main/**.master/target/jacoco.exec</sonar.jacoco.reportPath>
<jacoco.reports.outputDirectory>${basedir}/../../../main/**.master/target/site/jacoco</jacoco.reports.outputDirectory>
<sonar.sources>src</sonar.sources>

In the test projects (eclipse-test-plugin) we changed added the property sonar.sources to go find the sources from the src folder of the project that we're testing for example in client.admin.test.fragment we go search the src from the client.admin

The following properties were commented in code because they're not supported in maven according to documentation and to the debug output.

<!--<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>-->
<!--<sonar.tests></sonar.tests>-->
<!--<sonar.java.binaries></sonar.java.binaries>-->
1
Turn on debug mode during your compilation. You have Manve. I use Gradle and to solve the issue, I did this to turn -g option for compiler args and turning debug mode on. You can do similar in Maven pom.xml or global/parent level file: tasks.withType(Compile) { options.debug = true options.compilerArgs = ["-g"] }AKS
Other thing, if you are trying to get coverage from non-unit tests, then jacocoagent.jar needs to be attached to the target JVM (where you run the .war i.e. behind Tomcat.. so you have to attach jacocoagent.jar to that Tomcat's JVM while starting Tomcat) or you'll see 0% coverage.AKS
@ArunSanagal Maven's and Tychos compilation have debug option activated by default and the build is also run in debug mode. The reporting info contains the jacoco coverage report and coverage is different than zero so jacoco agent is working on the run. The problem here is that sonar when runing sonar:sonar is not able to get that information.Betty Sanchez
what all params are you passing. I mean, are you successfully passing -Dsonar.xxx to sonar.zzz all those variable for reports (Unit and Integartion test)? -Dsonar.dynamicAnalysis=reuseReports -Dsonar.surefire.reportsPath=build/test-results -Dsonar.sources=src/java,test/java -Dsonar.jacoco.reportPath=build/jacoco/test.exec -Dsonar.jacoco.itReportPath=build/jacoco/integrationTest.exec -Dsonar.binaries=build/classes etc etc. -Dsonar.jacoco.reportPath and -Dsonar.jacoco.itReportPath are the two main variables and you have the give valid values for these variables using what/where Maven generatesAKS
You can do one thing. For testing purpose, instead of using mvn sonar:sonar, try running sonar-runner (unix command utility provided by SonarQube team) manually on the Project's workspace. Before your run sonar-runner executable, you have to create a "sonar-project.properties" file in that project's workspace. Inside this file, you define all the variables like: sonar.projectName=Koba and in the next line for ex: sonar.projectKey=xxx:company:zzz:Koba ... sonar.jacoco.reportPath=<relative_path_to_your_jacoco_exec_file_for_unit_tests .. sonar.jacoco.itReportPath=.../jacoco_for_it_tests.exec etc.AKS

1 Answers

1
votes

First, you must tell the JaCoCo agent to report all coverage data into one common file. Second, you tell the Sonar JaCoCo plugin to read the coverage data from the aggregated file.

To do so, set the properties "jacoco.destFile" and "sonar.jacoco.reportPath" in your parent pom.xml to the same absolute path, e.g.:

<properties>
    <jacoco.destFile>/home/jenkins/jobs/my.project/workspace/parent/target/jacoco.exec</jacoco.destFile>
    <sonar.jacoco.reportPath>/home/jenkins/jobs/my.project/workspace/parent/target/jacoco.exec</sonar.jacoco.reportPath>
</properties>

Note that these properties will be inherited to all child poms, so you can't use Maven expressions like ${project.build.directory} because this would evaluate to a different directory for each pom.

You could create a small helper Mojo which automatically resolves an absolute path on the current build machine and then injects the properties into the Maven model.