JaCoCo with multi-module Maven project - Only record coverage by module owned tests - maven

We have a large Maven project with about 50 modules. Today we have a good setup where we get a combined JaCoCo coverage for the whole project. We also use the final binary generated by JaCoCo for custom coverage logic.
We would like to implement a more strict coverage policy where only tests in the same module contribute to the overall coverage. We want every module to be responsible for its own tests and coverage.
For example. Module A depends on module B. A has code that makes use of code in B. When tests in A is run, we do not want to have coverage from any class in B recorded.
Is this setup possible? Trying around, I find that JaCoCo has many options for filtering when generating the final report, but I'd like to do this in the first step, when the coverage is collected.
Eventually, I'd like to end up with a JaCoCo exec file in each module's target directory that only has classes recorded from its own module. It would be perfectly fine if we had to do some configuration on a module-by-module basis like having an explicit package expression for inclusion.

Trying around, I find that JaCoCo has many options for filtering when generating the final report, but I'd like to do this in the first step, when the coverage is collected.
There is also options for filtering during collection - see includes and excludes options of JaCoCo Java Agent and corresponding options of prepare-agent in jacoco-maven-plugin.
Build of JaCoCo itself uses them exactly for this.

Related

Sonarqube gradle plugin - excluding test sources breaks the unit test count in report

I'm using Gradle sonarqube plugin and I need to exclude all test sources from the sonar analysis (main goal is to filter out unit test classes from the issues/code smells report)
To do so, I have used the dedicated sonar.test.exclusions property as follow, to exclude the whole src/test directory from analysis
sonarqube {
properties {
property("sonar.exclusions" , "")
property("sonar.test.exclusions" , "src/test/**/*.java")
// other sonar properties, omitted
}
}
This works as expected (test sources are filtered out) BUT : when this property is set, sonar does not compute/report number of unit tests correctly.
See simple example for a very basic project: 2 main source files, 1 test source file containing 2 Junit tests (and also containing some issues I don"t want to see in report)
Without exclusions:
Sonar properly reports my 2 unit tests, but it also includes code smells from the unit test class
With exclusions:
Now, code smells from the unit test are properly filtered, but I lost the Unit test count information
Notes:
using Gradle 6.7, sonarqube plugin version 3.0, and sonar server Community EditionVersion 8.4.2
also tried with the property sonar.exclusions : same problem
all other sonar properties are correctly set and have same values in both scenarios : specially sonar.tests, sonar.java.test.binaries, sonar.junit.reportPaths, sonar.jacoco.reportPath
Any idea how to configure the sonarqube plugin, to exclude properly test sources, while keeping Unit tests information available?
I agree with Chriki's answer but only the first part : using sonar.test.exclusions is not the good way.
I disagree with the last part : using sonar.issue.ignore.multicriteria is totally possible with Gradle
https://www.baeldung.com/sonar-exclude-violations#using-sonar-projectproperties
Try something like this (not tested from my end though) :
sonarqube {
properties {
property "sonar.issue.ignore.multicriteria", "e1"
property "sonar.issue.ignore.multicriteria.e1.resourceKey", "src/test/java/**/*"
property "sonar.issue.ignore.multicriteria.e1.ruleKey", "*"
}
}
What you’re after doesn’t seem to be possible from a Gradle configuration. Let me elaborate on how I came to that conclusion.
In a (admittedly very) old thread on the Sonarqube mailing list from 2013, somebody asked the same question (albeit for Maven). A Sonarqube consultant has answered it as follows:
When you exclude a file (or a test file) with sonar.exclusions (or sonar.test.exclusions), the file is just ignored by SonarQube. The source code is not imported, no metrics are computed on this file (such as number of tests).
To ignore some specific issues on specific files, see http://docs.codehaus.org/display/SONAR/Narrowing+the+Focus#NarrowingtheFocus-IgnoreIssues. To ignore some files to be taking into account for code coverage computation, see http://docs.codehaus.org/display/SONAR/Narrowing+the+Focus#NarrowingtheFocus-IgnoreCodeCoverage and so on.
The current documentation link corresponding to the first (now broken) one from the quote is this: https://docs.sonarqube.org/latest/project-administration/narrowing-the-focus/#header-3 (or for version 8.4) It’s about ignoring “issues on certain components and against certain coding rules” – which is what you’re after, if I’m not mistaken. However, these docs state right at the beginning:
Note that the properties below can only be set through the web interface because they are multi-valued.
Here “web interface” is meant as opposed to a (Gradle) build configuration for example. In fact, the previously mentioned Sonarqube consultant explicitly states this for Maven, too:
The property is sonar.issue.ignore.multicriteria. I think I read somewhere that you have to do these through the GUI because they are multi-valued? Is that the case? If not, how would I write it as an entry in the pom.xml? We like to keep all config in the one place (pom.xml).
It's unfortunately not possible.
The mailing list discussion is a bit longer and gives more insight, so it may be worth a read in full. It also sheds some more light on the sonar.test.exclusions property for which I could otherwise not find any good documentation.

JaCoCo ignoring Lombok code, is this expected?

I am using Lombok 1.18.2 and JaCoCo 0.8.3, which theoretically recognize/ignore lombok annotations. I did a test, added the lombok.addLombokGeneratedAnnotation = true param in my lombok.config and then I see the generated annotation on my target classes decompiled code.
But I am surprised to open jacoco.exec file and see that things like #Getter increase the "Total Probes" values, but keep untouched the "Executed Probes" one.
Is this expected?
If so, how can SonarQube make smart use of it, if by pointing it to the jacoco.exec files, there is only information on total/hit probes? How can Sonar tell one of this probes has something to do with lombok?
I am using Lombok 1.18.2 and JaCoCo 0.8.3, which theoretically recognize/ignore lombok annotations.
Not theoretically, but practically.
Not "ignore lombok annotations", but methods annotated with #lombok.Generated, or even more precise quoting entry from 0.8.3 changelog:
Classes and methods annotated by annotation whose retention policy is runtime or class and whose simple name contains "Generated" (previously equality was required) are filtered out during generation of report
But I am surprised to open jacoco.exec file and see that things like #Getter increase the "Total Probes" values, but keep untouched the "Executed Probes" one. Is this expected?
Yes, this is expected. Filtering of methods doesn't happen during instrumentation of classes (insertion of probes). exec file is not final report, it contains raw information about all probes inserted in class. Filtering of methods happens during generation of report (analysis of exec and class files), i.e. during execution of report JaCoCo Ant Task for example.
If so, how can SonarQube make smart use of it, if by pointing it to the jacoco.exec files, there is only information on total/hit probes? How can Sonar tell one of this probes has something to do with lombok?
SonarQube embeds JaCoCo as a library and use it to analyze exec and class files for generation of their report.
And that's why JaCoCo release announcements usually contain following statement, e.g. for 0.8.2:
As before - please note
0.8.2 version of integrations developed as part of JaCoCo project by us (Ant Tasks, Maven Plugin and Command Line Interface) provide Java 11 support and new filters,
tools that directly read exec files (which is not a final report) and embed JaCoCo as a library for generation of report will provide ability to analyze Java 11 class files and to use new filters only after they updated to this version of JaCoCo.
So please follow/wait/etc respective vendors such as
SonarQube - https://jira.sonarsource.com/browse/SONARJAVA-2876 , or try to use new plugin that reads XML report - https://github.com/SonarSource/sonar-jacoco

How to order unit test execution from Gradle?

Is there any way to specify the order of the unit tests classes run by a Gradle Test task?
I'd like to get some known longer-running tests at either the front or the back of the list, but don't know if it's possible without splitting my tests' execution between multiple tasks.
Running JUnit 4.12 and Gradle 4.5.
Gradle simply delegates execution to the JUnit runner.
So if you want specific test class ordering, you will need to create a Suite and specify the test classes in the order you want, see the JUnit documentation for this.
Now, given the flexibility of Gradle in terms of having different source roots, I would strongly recommend doing the separation at the Gradle level, by create extra test source roots, test task and the like. This will allow you to effectively control when these long running tests are run in a standard build execution, but also to skip them or run these only when desired. The ordering at the JUnit level will not give that flexibility without much more tweaking. See the Gradle documentation on adding source sets.

How to get Sonar to report both Java and JavaScript tests run by Maven

Our project uses Maven as the build tool and we are using Sonar to track quality. JUnit tests are executed by SureFire and the results are displayed in Sonar. We've added some JavaScript tests which are run by the jasmine-maven-plugin and want to include these results in the Sonar project.
The plugin generates a JUnit style XML report. How should we go about including the XML report in Sonar? Do we want to merge the XML reports as part of the build maybe?
You need to be sure the format generated by Jasmine is compliant with the JUnit XML format expected by the JavaScript Plugin : http://docs.sonarqube.org/display/PLUG/JavaScript+Unit+Tests+Execution+Reports+Import
You can also have a look at the format supported by the Generic Test Coverage Plugin : http://docs.sonarqube.org/display/SONAR/Generic+Test+Coverage
You don't need to merge the XML reports, there are different sonar.* properties to feed depending on the way you want to load your data: thru the JavaScript Plugin or the Generic Test Coverage. As a consequence, you don't need to run SonarQube analysis twice.

Sonar + Multi Module Maven Projects

I am calling Sonar from my Jenkins job
I noticed that the coverage of the classes in my domain module all show as having 0% test coverage even though the domains are being used in the other modules which have high test coverage. I am using cobertura within Sonar for measuring the coverage
Can anyone offer any insights into how to get Sonar/Cobertura to recognise the test coverage for the classes in the domain module
Thanks
Damien
By default, Sonar computes unit test coverage. So if your domain classes are not unit-tested in the module where they are defined, this is normal that you don't get unit test coverage for those.
You can have a look at how to add integration test coverage in Sonar: see https://github.com/SonarSource/sonar-examples/tree/master/projects/code-coverage/combined%20ut-it/combined-ut-it-multimodule-maven-jacoco
But that'd be best to have "real" unit tests for your domain classes to test their logic in an isolated context.
Edit
Link to sonar-exmaple-multiple-modules

Resources