Maven: Add Test Directory From Command Line - java

Is there a way to include a test folder for Maven to compile from the command line?
I have a set of tests that are in a folder that are not part of the standard set of unit and integration tests. These tests are still useful to run individually until the needed integration tests are built. In Eclipse, I can run these tests individually by right clicking on them and running them as a JUnit test. I am finding that I often want to run more than one test, so I am trying to run them from Maven on the command line. In Maven I can do something like this:
mvn -Dtest=OldTest,OlderTest test
The problem I think I have is that the folder that these tests sit in is not listed as part of the set of test files that need to compile in the POM. I would like to temporarily add the folder, run the tests, and remove the folder without modifying the POM.

I use the Build Helper plugin to add in integration test sources when a certain profile has been activated, for example:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/it/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
Perhaps you can do something similar?

Related

Change maven profile from within project

I want to change maven project's active profile from within the maven project.
The java project has 3 classes having main methods and they are executed one by one, All of these require different set of dependencies.
I would like to run these classes with different maven profiles.
For example my project project1 is a maven project and is getting invoked by mvn clean package spring-boot:run command.
When the control comes to the project1 it executes the java classes one by one.
My requirement is that when ClassA is run it should change the current maven profile to profile1 (recompiling the same project is ok, performance is not priority). Similarly when ClassB gets invoked it should change the current maven profile to Profile2.
(Note these classes are dynamically picked from directory using reflection and only the class will know what profile it supports)
Is there any way maven allows this at runtime.
If not what is the best way to achieve this.
maven profiles are not designed for such tasks, what you are actually need to do is to setup different executions for each class:
...
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>run-clsa</id>
<goals>
<goal>run</goal>
</goals>
<phase>none</phase>
<configuration>
<mainClass>ClassA</mainClass>
</configuration>
</execution>
<execution>
<id>run-clsb</id>
<goals>
<goal>run</goal>
</goals>
<phase>none</phase>
<configuration>
<mainClass>ClassB</mainClass>
</configuration>
</execution>
</executions>
...
and run that in following way:
mvn clean package spring-boot:run#run-clsa
mvn clean package spring-boot:run#run-clsb

What current code coverage tools for Java can show coverage from a tests point of view?

There are many code coverage tools that reached the end of life which makes looking up tools a bit difficult. I'm wondering if anyone has experience with a tool that can show code coverage from a test point of view for Maven projects in Java.
Something like this:
Test: myTest
Coverage:covers 30 % of source code.
and export this result in either XML or JSON.
Example with Jacoco. From information written by #cesarsotovalero
Run one test method with
mvn clean verify -Dtest=yourTestClass#yourTestMethod
Or run a test class with
mvn clean verify -Dtest=yourTestClass
Or run the whole test suite with
mvn clean test
The name of the test/s will now exist in \target\surefire-reports\TEST-yourTest.xml
The coverage results will be in \target\site\jacoco\jacoco.xml
Now you can read the test name/s and map it to the test result/s. At the bottom of the XML in \target\site\jacoco\jacoco.xml there is a summary:
<counter covered="10" missed="19" type="INSTRUCTION"/>
<counter covered="3" missed="5" type="LINE"/>
<counter covered="3" missed="2" type="COMPLEXITY"/>
<counter covered="3" missed="2" type="METHOD"/>
<counter covered="2" missed="0" type="CLASS"/>
Test coverage for the test in \target\surefire-reports\TEST-yourTest.xml is
3 / (3+5) = 37,5 %
JaCoCo does exactly what you're asking for. Add it as a plugin to the pom.xml file of your Maven project as follows:
<build>
<plugins>
<!-- JaCoCo plugin-->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</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>
</plugins>
</build>
To get the % of coverage of a single test, run:
mvn clean verify -Dtest=myTestClass#myTestMethod
The coverage results will be exported to ./target/site/jacoco/jacoco.xml. Also, a nice HTML report will be generated at ./target/site/jacoco/index.html.
You can parse the jacoco.xml file to get the coverage of the test w.r.t the tested class: (lines missing + lines covered) / lines covered.

JaCoCo Offline Instrumentaion and Integration Test Coverage Reports

I have been trying to implement JaCoCo offline code coverage in a JBoss server using an instrumented EAR for deployment and the jacococagent.jar in order to track code coverage of external integration testing running against said JBoss.
I have been following guides such as these:
http://www.eclemma.org/jacoco/trunk/doc/offline.html
http://automationrhapsody.com/code-coverage-with-jacoco-offline-instrumentation-with-maven/
I feel I am pretty close as everything SEEMS to be working, however, when I load the coverage report up in eclipse's EclEmma plugin, it reports as 0 coverage for everything (which I know is wrong).
Here's my setup:
Here's the maven plugin configuration:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<configuration>
<!-- <destFile>${sonar.jacoco.reportPath}</destFile> -->
<append>true</append>
<excludes>
<exclude>**/dao/**/*Dao*</exclude>
<exclude>**/dao/**/*DAO*</exclude>
<exclude>**/dao/**/*Vo*</exclude>
<exclude>**/dao/**/*VO*</exclude>
<exclude>**/ui/**/*</exclude>
<exclude>**/*Vo.*</exclude>
<exclude>**/*VO.*</exclude>
<exclude>**/test/**/*</exclude>
<exclude>**/tester/**/*</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${sonar.jacoco.reportPath}</destFile>
</configuration>
</execution>
<execution>
<id>unit-test-report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${sonar.jacoco.reportPath}</dataFile>
</configuration>
</execution>
<execution>
<id>jacoco-instrument</id>
<phase>test</phase>
<goals>
<goal>instrument</goal>
</goals>
<configuration>
<skip>${jacoco.skip.instrument}</skip>
<!-- <skip>false</skip> -->
</configuration>
</execution>
</executions>
</plugin>
Here's my jacoco-agent.properties file:
destfile=/stage/live_integration_jacoco.exec
output=file
dumponexit=true
append=true
I'm bundling the JaCoCo Agent JARs right inside the EAR as these dependencies (the second one is just what jacocoagent.jar is labelled as in our repository):
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.agent</artifactId>
<version>${jacoco.version}</version>
</dependency>
<dependency>
<groupId>org.jacoco.build</groupId>
<artifactId>org.jacoco.jacocoagent</artifactId>
<version>${jacoco.version}</version>
</dependency>
Here's my process:
I run this on the project: mvn clean install -U -Djacoco.skip.instrument=false
And that generates my instrumented EAR artifact. I have verified that the classes in there are indeed instrumented by JaCoCo by decompiling a few of them.
I take that EAR that has instrumented code, the jacococagent.jar included in it, and the jacoco-agent.popreties file included as well and deploy that to JBoss. JBoss starts just fine (it used to get ClassNotFound exception before I started bundling jacocoagent.jar in it directly).
The "/stage/live_integration_jacoco.exec" file is created at this point with a size of '0'.
I run some tests on and against the server, even some manual testing, then stop the application.
The "/stage/live_integration_jacoco.exec" file now has data (30-60kb of data so far in my observations).
I import that exec file into eclipse and it loads without any errors and shows the classes in the project, however it reports 0 coverage on everything.
Well, I'm not sure what else to try at this point.
Does anyone have some thoughts on how to get it correctly generating the coverage report in my situation?
Thanks!
I suspect that classes deployed on server are compiled with Oracle Java compiler, while classes in Eclipse are compiled with Eclipse Java compiler, and hence JaCoCo can't associate them since they differ. To confirm this - you can try to generate report using the exec file that you try to import, but outside of Eclipse using Ant or Maven. And make sure that you execute generation of report on original (non instrumented) classes, otherwise they also won't match.

How to make SonarQube module analyze the project only once when sonar analysis is bound to maven lifecycle in a multi-module project?

What I am trying to achieve is integrate SonarQube analysis into the build process, so that whenever mvn clean install is run, the code is analyzed with SonarQube. We want to use it for local analysis and also for build on Jenkins. If new issues are found, than the build should fail (we want to use build breaker plugin for that). This way the developer would know that by his code his is going to introduce new issues, and will have to fix them for the build to work.
When I run mvn sonar:sonar, the analysis takes 30 seconds, which is OK.
However, the problem occurs when I am trying to bind sonar goal to maven build phases. I bind sonar to verify phase. The build takes 5 minutes now, which is too long. It should take about 1 minute. The build itself, without SonarQube analysis takes 30 seconds.
Note (may help to figure out what the problem is): the project on which the build is run has multiple modules in it, and I guess that is the problem. It looks like sonar:sonar goal is executed multiple times, once for each submodule, and the whole project is analyzed multiple times (not only the submodules). So, we have 4 submodules, and the report is generated 5 times during the build.
Instead, we want to analyze the whole project only once, not 5 times. It's also important for this 1 analysis to be run at the end of the build, after the cobertura reports are generated for all modules.
So, how do I integrate SonarQube analysis into the build, so that it analyzes my multi-module project only once, in the end, after cobertura reports are generated for all the submodules?
SonarQube plugin properties in parent pom:
<!-- Sonar plugin properties -->
<sonar.jdbc.url>jdbc:url</sonar.jdbc.url>
<sonar.analysis.mode>preview</sonar.analysis.mode>
<sonar.issuesReport.html.enable>true</sonar.issuesReport.html.enable>
<sonar.issuesReport.console.enable>true</sonar.issuesReport.console.enable>
<sonar.host.url>sonar.host:9000</sonar.host.url>
<sonar.language>java</sonar.language>
<sonar.buildbreaker.skip>false</sonar.buildbreaker.skip>
<sonar.qualitygate>Sonar%20way%20with%20Findbugs</sonar.qualitygate>
<sonar.preview.includePlugins>buildbreaker</sonar.preview.includePlugins>
<sonar.exclusions>file:**/target/**</sonar.exclusions>
<branch>development</branch>
Plugins configuration in the project pom:
<!-- Run cobertura analysis during package phase -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>cobertura</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Run sonar analysis (preview mode) during verify phase. Cobertura reports need to be generated already -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sonar</goal>
</goals>
</execution>
</executions>
</plugin>
IMO, this is just a Maven configuration issue, you're missing the <inherited>false</inherited> element on the execution of sonar:sonar:
<!-- Run sonar analysis (preview mode) during verify phase. Cobertura reports need to be generated already -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sonar</goal>
</goals>
<inherited>false</inherited>
</execution>
</executions>
</plugin>

maven yui compression on war:war

I'm trying to automatically compress both CSS and JS using maven and this plugin. I want to compress when the goal war is executed but I'm not figuring how:
<build>
<finalName>${artifactId}-${version}-production</finalName>
<plugins>
<plugin>
<groupId>net.sf.alchim</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<executions>
<execution>
<configuration>
<gzip>true</gzip>
<nosuffix>true</nosuffix>
</configuration>
<goals>
<goal>compress</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
You need to bind the execution to a phase so it will be executed when you run the war packaging. These are the available phases you can bind to for war packaging.
<plugin>
<groupId>net.sf.alchim</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<executions>
<execution>
<id>compress</id>
<phase>process-resources</phase>
...<!--rest of config is fine-->
Update: Are the js.gz files not being generated or just not included in the war?
One additional thing to check if you're still not seeing the content in the war is that the resources should be under src/main/resources, not src/main/webapp.
The yuicompressor plugin will process the js files in src/main/webapp, but they won't be included in the final war.
Update 2: reread your question after seeing your answer, I'd misread the goal you were running. To avoid running two goals you can do one of these:
Try instead of running the war goal, run install or package, this will invoke the standard lifecycle, and the yuicompressor plugin will be invoked in the process-resources phase.
Alternatively change the phase the yuicompressor goal is bound to in the example above to package so it is activated when you run the war:war goal.
for some weird reason war:war doesn't call the plugin in the phase process-resources: I just added a custom menu on nb 6.7 that call first compile, then war:war

Categories