Jacoco Exclude Packages Not Reducing Total Lines to Cover - maven

I'm trying to exclude some packages from the Jacoco coverage scan, but it's not working like how I would expect. Here's my Maven POM configuration for Jacoco:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.0</version>
<configuration>
<excludes>
<exclude>**/pojo/**/*</exclude>
</excludes>
</configuration>
</plugin>
The behavior I'm experiencing is that the files are being set to 0% lines covered instead of reducing the total lines to cover, which is actually reducing my coverage percentage. So how do I correct this?
EDIT: A workaround for this issue is to remove the file entirely from SonarQube using sonar properties:
<sonar.exclusions>**/pojo/**/*</sonar.exclusions>
However, this is just a workaround since now I can't see code smells from those files (there probably aren't any since they are POJOs, but I like the sense of security of knowing for a fact there are no code smells).

Total lines of code in Sonar are not totally managed by Jacoco. You need to add this property to your pom.xml:
<properties>
<sonar.coverage.exclusions>**/pojo/**/*</sonar.coverage.exclusions>
</properties>

Related

How to determine what are the attribute necessary to add a plugin in pom.xml

Since last few days a lot of doubts got cleared because of the you all experts. I have one more question, when i see my pom.xml in my project , I see a lot of plugins with quite a few configuration. for e.g
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit-platform</artifactId>
<version>3.0.0-M4</version>
</dependency>
</dependencies>
<configuration>
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
<argLine>${argLine} -Xmx4g -XX:MaxPermSize=1g</argLine>
<includes>
<include>**/*Test.java</include>
<include>**/*Spec.java</include>
</includes>
</configuration>
</plugin>
My question is how they decided the these forkcount , argLine needed to be used here? plus the dependency also. When i checked the bealdung doc for same plugin the config was very simple. is it necessary to read docs for a perticular plugin before using it. like how people take decisions for the same that what are the tags to be used or what are the mandatory tags. any links will be helpful.
Thanks
I strongly recommend reading the docs of the appropriate plugin which would show like in your example defining the provider (the dependency) https://maven.apache.org/surefire/maven-surefire-plugin/examples/providers.html is usually not needed nor helpful/useful. For the other settings it depends on what kind of tests you are running but from my point of view I would strongly review my tests because needed to set 4 GiB for heapspace sounds weird .... especially for a tests? The others parts depends on the testing framework you are using.. and your use case. I usually start without any configuration for my builds ...only If i really need to change something I do so which is rarely the case. (Convention over configuration)... and read the docs: https://maven.apache.org/surefire/maven-surefire-plugin/plugin-info.html

Difference between v2.18 and v2.22.0 of Maven surefire plugin

I configured surefire v2.18 to exclude tests in packages like e2e.com.mycompany.myapp but not like com.mycompany.myapp.e2e and it was working but if I use v2.22.0 I get a different behavior: both are excluded. Is it a bug?
My configuration is:
<configuration>
<excludes>
<exclude>e2e/**</exclude>
</excludes>
</configuration>
I also tried with:
<configuration>
<excludes>
<exclude>e2e/**/*Test*.java</exclude>
</excludes>
</configuration>
How can I get the same behavior with the new version? I'm using Maven 3.3.9.
You could go through following link which explains enhancements made with v2.19 onwards for exclusion and inclusion of tests:
https://maven.apache.org/surefire/maven-surefire-plugin/examples/inclusion-exclusion.html
Following is brief snapshot captured from above link for inclusion and exclusion of packages and classes:
Following link explains release notes for v2.22:
https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12317927&version=12343425

How do I configure my Maven-war-plugin's useCache feature so that consecutive builds are faster?

I’m using Maven 3.3.0 on Mac Yosemite. I wanted to make use of the maven-war-plugin’s useCache feature, but it isn’t doing anything in my multi-module project. When I run
mvn clean install -DskipTests
my project takes about 1:25 to run with the below configuration
<profile>
<id>prepare-deploy-war-to-jboss</id>
<activation>
<file>
<exists>${basedir}/src/main/webapp</exists>
</file>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<useCache>true</useCache>
<cacheFile>/tmp/${project.artifactId}/war/work</cacheFile>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Then I run the same command again and the project takes the same amount of time. I can see “work” files getting created so the plugin is definitely running but consecutive builds do not seem to be doing anything.
My question here isn’t so much as why isn’t useCache speeding up my build, but how can I configure my plugin differently so that consecutive runs do speed up the build? If there is another plugin I should be using that would speed up builds on back-to-back runs, then that would also suffice here.
Looking at the WAR mojo code (at the time of writing), the cache is mainly used by its web app structure concerning overlays management, so in most of the cases it would not improve build time indeed.
Moreover, as stated by its official documentation, the cache mechanism is an experimental feature, hence disabled by default, which probably doesn't achieve (yet) user expectations.
Regardless of the effectiveness of this cache option, some hints to speed up maven builds could be:
Consider whether you really need to clean at each and every run
Consider building offline (-o option) if everything you need is already on your local cache
Consider using threads during your build (-T option)
Consider going on quite mode (-q option), swithing off build log temporarely and getting only error logs (basically: no news, good news)
In your case, the War Plugin is activated upon the existence of a structure typical of a war packaging, which probably means this profile is part of the aggregator/parent pom and then activated only on the war module. Although it might impact very little, also consider moving the War Plugin configuration to its concerned module and avoid such a triggered configuration
Last but not least, during development time, build time is probably more important than war size, so you could switch off the default mechanism of re-compressing external libraries added to the war file, via the recompressZippedFiles option:
Indicates if zip archives (jar,zip etc) being added to the war should be compressed again. Compressing again can result in smaller archive size, but gives noticeably longer execution time.
Default: true
So a sample configuration would look like:
<properties>
<war.recompress.files>false</war.recompress.files>
</properties>
<build>
<finalName>webapp</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<recompressZippedFiles>${war.recompress.files}</recompressZippedFiles>
</configuration>
</plugin>
</plugins>
</build>
Note: since there is no user property for this configuration entry, I also added a property for it, to switch it on/off on demand via command line (or via profile).
You could then test the different execution times executing the default build (with the configuration above disabling recompression) against the previous configuration (below, switching recompression on for the current execution, on demand):
mvn clean install -Dwar.recompress.files=true
You may then consider to profile it to switch it on/off depending on development phase.

Maven + AspectJ/SpringAOP + Lombok + Surefire = test broken in a specific scenario

I have an interesting problem in a project where all of the technologies mentioned in the title are used. I've been able to track it down up to the diagnosis (the test classpath prepared by Surefire), but I don't understand whether it can be fixed and how. It's not a showstopper, indeed it's a minor issue for me, but I'd like to solve it anyway.
First a rough description.
The problem is related to executing tests in a specific module of the project, and only in a specific way.
Everything works (tests pass) when I run from the master pom level:
cd ${projHome}
mvn install
Everything works (tests pass) when I run:
cd ${projHome}/modules/CoreImplementation/
mvn test
That means that I can build and test with no problems, the same for my Jenkins, and NetBeans can run tests from the IDE when I need them.
But that module fails testing when I run from the master pom level:
cd ${projHome}
mvn test
with this error:
java.lang.NoSuchMethodError: it.tidalwave.northernwind.profiling.RequestProfilerAspect.aspectOf()Lit/tidalwave/northernwind/profiling/RequestProfilerAspect;
at it.tidalwave.northernwind.frontend.ui.spi.DefaultSiteViewController.processRequest(DefaultSiteViewController.java:82) ~[classes/:na]
at it.tidalwave.northernwind.frontend.ui.spi.DefaultSiteViewControllerTest.must_call_some_RequestProcessors_when_one_breaks(DefaultSiteViewControllerTest.java:161) ~[test-classes/:na]
Running mvn test as a second pass (after a mvn install -DskipTests) happens to be the way Drone.io and Travis do their job. While I could change their configuration, I'd like to stay with the standard configuration and fix the problem if possible.
The diagnosis in short and my question.
Now, the question in short (details are further below). I was able to track down the problem to different ways in which Surefire prepares the classpath to execute the tests.
When I run mvn install the classpath is:
${repo}/org/apache/maven/surefire/surefire-booter/2.16/surefire-booter-2.16.jar
${repo}/org/apache/maven/surefire/surefire-api/2.16/surefire-api-2.16.jar
${projHome}/modules/CoreImplementation/target/test-classes
${projHome}/modules/CoreImplementation/target/classes
${projHome}/modules/Core/target/it-tidalwave-northernwind-core-1.1-ALPHA-37-SNAPSHOT.952b0c8bdc77.jar
${repo}/it/tidalwave/thesefoolishthings/it-tidalwave-role/3.0-ALPHA-1/it-tidalwave-role-3.0-ALPHA-1.jar
${projHome}/modules/Profiling/target/it-tidalwave-northernwind-core-profiling-1.1-ALPHA-37-SNAPSHOT.952b0c8bdc77.jar
${repo}/org/apache/commons/commons-math3/3.0/commons-math3-3.0.jar
…
When I run mvn test (from the project home) the classpath is:
${repo}/org/apache/maven/surefire/surefire-booter/2.16/surefire-booter-2.16.jar
${repo}/org/apache/maven/surefire/surefire-api/2.16/surefire-api-2.16.jar
${projHome}/modules/CoreImplementation/target/test-classes
${projHome}/modules/CoreImplementation/target/classes
${projHome}/modules/Core/target/unwoven-classes
${repo}/it/tidalwave/thesefoolishthings/it-tidalwave-role/3.0-ALPHA-1/it-tidalwave-role-3.0-ALPHA-1.jar
${projHome}/modules/Profiling/target/unwoven-classes
${repo}/org/apache/commons/commons-math3/3.0/commons-math3-3.0.jar
…
The different portions are the indented ones. In the former case, SureFire uses the classes directory (forget for a moment that in my case they are named unwoven-classes) only for the module under test, and the installed jar files for every dependency. In the latter case, it seems to be using classes for all dependencies in the reactor.
The reason for which this difference in the classpaths gives me troubles is explained below in the "Gory details" section. In short, that unwoven means that they contain bytecode not augmented by AspectJ, hence the methods that can't be found at runtime.
I'm running with SureFire 2.16, but I've also tried the latest 2.19 with no changes. Being able to force SureFire to always use jar files for dependencies would fix my problems. If you have the answer, you can stop reading my post here.
Gory details (just for curiosity).
The faulty module artifactId is it-tidalwave-northernwind-core-default and it depends on aspects available in it-tidalwave-northernwind-core-profiling - that's where the offending RequestProfilerAspect is. The aspect library dependency is both in the regular dependencies of the faulty module and in the configuration of the aspectj plugin:
<dependency>
<groupId>it.tidalwave.northernwind</groupId>
<artifactId>it-tidalwave-northernwind-core-profiling</artifactId>
</dependency>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<aspectLibraries combine.children="append">
<dependency>
<groupId>it.tidalwave.northernwind</groupId>
<artifactId>it-tidalwave-northernwind-core-profiling</artifactId>
</dependency>
</aspectLibraries>
</configuration>
</plugin>
</plugins>
</build>
AspectJ integration is by means of the following profile in a Super POM, which is activated in the build, whose relevant part is:
<profile>
<id>it.tidalwave-aspectj-springaop-v1</id>
...
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<configuration>
<outputDirectory>target/unwoven-classes</outputDirectory>
</configuration>
</execution>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<configuration>
<outputDirectory>target/unwoven-test-classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
...
The aspectj plugin is configured in the profile to statically weave binaries in the unwoven-test-classes directories. The reason for this approach is that it's the only feasible solution AFAIK to have both Lombok and AspectJ work together.
Now, back to the two classpaths described above: the fact that SureFire is using unwoven-classes means that it's pointing to bytecode that has not been augmented with AspectJ methods, hence the error.
References
The project is a FLOSS one and can be found at
https://bitbucket.org/tidalwave/northernwind-src
or
https://github.com/tidalwave-it/northernwind-src
A changeset where the problem can be reproduced is f98e9a89ac70138c1b6bd0d4570a22d59ed71be6. JDK 1.8.0 is required to build the project (even though it doesn't use Java 8 code yet).
The SuperPOM can be found here:
https://bitbucket.org/tidalwave/thesefoolishthings-superpom-src

How to access maven.build.timestamp for resource filtering

I am using maven 3.0.4 and would like to make the build timestamp accessible to my application. For this, I'm putting a placeholder in a .properties file and let maven filter on build. While this is working fine for ${project.version}, ${maven.build.timestamp} is not substituted on filtering.
The property seems to be available on build - I can use it to modify the artifact name:
<finalName>${project.artifactId}-${maven.build.timestamp}</finalName>
So why is it not available for resource filtering? And, more importantly, how do I make it accessible?
I have discovered this article, explaining that due to a bug in maven, the build timestamp does not get propagated to the filtering. The workaround is to wrap the timestamp in another property:
<properties>
<timestamp>${maven.build.timestamp}</timestamp>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
</properties>
Filtering then works as expected for
buildTimestamp=${timestamp}
I can confirm as of Maven 3.x {maven.build.timestamp} is "working" now. They work arounded the problem, apparently. No additional properties workaround needed anymore.
However, be careful your "filtering" plugin (maven-resources-plugin) is up to date. It needs to be relatively new, so if mvn help:effective-pom shows an old version (ex: 2.6), bump it to something newer, fixed it for me, 3.x ex:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<properties><timestamp>... workaround is no longer required...
This also cleared up, kind of, why it was working in IntelliJ but not the command line. IntelliJ probably uses their own "modified/internal" maven constants, so it was working there, but not from maven command line.
Also note if you add a filtering resource directory to you pom, you may need to also "re-add" the default directory, it gets lost, ex:
<resource>
<directory>src/main/resources-filtered</directory> <!-- to get "maven.build.timestamp" into resource properties file -->
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory> <!-- apparently have to add this is you have the other... -->
</resource>
NB if you're using spring boot as your parent, you have to use #maven.build.timestamp# instead. Also note if you're using spring boot there's a file META-INF/build-info.properties that is optionally created by the spring-boot-maven-plugin that you can read (spring provides a BuildProperties bean for convenience reading it).
In order to enrich the Stackoverflow content for others, that like me, found this post as a way to solve the "problem" of ${maven.build.timestamp}. This is not a maven bug, but an expected behavior of m2e, as can be seen in this post.
Therefore, I believe that we can not expect the solution to be "corrected", since, from what I understand, the correction involves conceptual issues.
In my case, what I did was use the plugin (buildnumber-maven-plugin) as described in this other post.
Adding Maven properties at the pom project level doesn't take into account correct local Timezone, so timestamp may appear wrong :
<properties><timestamp>${maven.build.timestamp}</timestamp></properties>
Using the build-helper-maven-plugin applies the correct timezone and current daylight saving to the timestamp :
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>timestamp-property</id>
<goals>
<goal>timestamp-property</goal>
</goals>
<configuration>
<name>timestamp</name>
<pattern>yyyy-MM-dd HH:mm:ss</pattern>
<timeZone>Europe/Zurich</timeZone>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
When packaging, Maven will replace any token timestamp in /resources folder, e.g. resources/version.properties :
build.timestamp=${timestamp}
You can then load this properties file in your Application.

Resources