maven-assembly-plugin causing tests to run twice - maven-2

I have a maven project where I am using the assembly plugin.
I typically create my artifacts by running:
mvn clean verify assembly:assembly
(I have integration tests which I want run separately to unit tests).
When this runs, the assembly plugin is running the unit tests itself.
This causes them to be run twice.
Is there a way I can tell the assembly plugin not to run the tests?
I am tempted to run this in two steps:
1. mvn clean verify
2. if previous command successful, run mvn assembly:assembly -DskipTests=true
However, this is a little clumsy and would rather the single command.
Thanks,
Steven

When this runs, the assembly plugin is running the unit tests itself. This causes them to be run twice.
The assembly:assembly goal Invokes the execution of the lifecycle phase package prior to executing itself and running it on the command line will thus invoke any phase prior to package. And this includes the test phase.
Is there a way I can tell the assembly plugin not to run the tests?
No. My suggestion would be to create the assembly as part of the build lifecycle instead of invoking the plugin on the command line i.e. to bind it on a particular phase. For example:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<executions>
<execution>
<id>create-my-assembly</id>
<phase>package</phase><!-- change this if not appropriate -->
<goals>
<goal>single</goal>
</goals>
<configuration>
...
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
And if you don't want the assembly to be created if your integration tests fail, then bind it on a later phase (e.g. post-integration-test or verify).
And if you don't want the assembly to be systematically created, put the above configuration in a profile.

Related

How do I generate surefire report for all tests and make this work with jenkins?

I have a large number of Junit tests running selenium on eclipse, what I would like to do is generate a Junit or surefire report for the tests after all of them are run. I know that with maven you can do this for individual tests by running mvn test on the console and generating a report with:
mvn surefire-report:report-only
However, this tests and produces a report for each individual test, is there a way to make this work for multiple tests? The reason behind this is because I run these tests headlessly on Jenkins, I know that jenkins email plugin can allow me to pass a html report post build which would give me an idea of test success and failure.
You can try using this command:
#mvn clean test
This will clean the existing reports and run all test cases in one go and generate surefire-reports for all.
Please let me know if this what you are looking for. :)
Firstly you need to have all the right plugins and dependencies in your pom.xml file.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
</plugin>
</plugins>
</build>
<!-- `mvn clean test site` to generate the junit html report-->
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>3.0.0-M4</version>
</plugin>
</plugins>
</reporting>
Following this add the maven command to your maven build as shown.
After you run this your IDE will run all the tests in that maven build and generate a surefire.html report which can be found in target/site/surefire-report.html
(You may need to update your maven project to see the folder come up for the first time by right clicking the project, then hover over maven and then click update maven project.)
I would advise doing this as it then works with jenkins when it runs your tests in headless mode which can then be attached to your email extension plugin.

skip the execution of maven-war-plugin

How do I skip the execution of the maven-war-plugin during a mvn command?
Based on the documentation, it seems like I should be able to do so by running something like the following, using -Dmaven.war.skip=true:
mvn verify -P integration-test -Dmaven.war.skip=true
But when I do that the maven-war-plugin still gets executed.
Also strange is that when I remove the maven-war-plugin from my pom altogether, it still gets executed. That leaves me wondering why maven-war-plugin is getting executed at all, as I don't have it mentioned anywhere in my pom.xml.
So maybe a better question is: what brings the maven-war-plugin into the project if I don't have it listed as a plugin?
As it turns out, removing the packaging of my pom to war (<!--<packaging>war</packaging>-->) keeps the maven-war-plugin from executing. The maven-jar-plugin gets executed instead. That's not really what I want (I just want to run integration tests via mvn verify without taking too long). But it runs quicker at least.
You must override the default war execution.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<skip>true</skip>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>war</goal>
</goals>
</execution>
</executions>
</plugin>
Explanation
By default, the war goal binds to the package lifecylcle phase as stated in the documentation.
So we override the package execution in the pom with the skip configuration.
You need to override executions configuration of maven war plugin:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webappDirectory>target/stampli-output/</webappDirectory>
</configuration>
<executions combine.children="override">
</executions>
</plugin>
It should do.
Why those instructions?
There is something like super-pom for every pom that has some standard defaults.
These defaults will be merged with your configuration if you don't override them.
Therefore also executions will be merged, which bind plugin goals with phase in mvn.
Links to read:
https://maven.apache.org/ref/3.0.4/maven-model-builder/super-pom.html
https://maven.apache.org/plugins/maven-help-plugin/effective-pom-mojo.html
https://maven.apache.org/pom.html#build - it has info on combine.children
https://maven.apache.org/guides/mini/guide-configuring-plugins.html

howto disable compile of modules when tests are skipepd

In our "big build" (40+ modules), we have several modules that contain only tests.
When I give -DskiptTests to mvn, the tests are not executed.
But they are compiled, which costs up to a minute of build time.
How can I selectively turn off such modules when the option skipTests is set?
You'd have to organize your root pom such that the test modules are activated via a profile, and instead of using -Dmaven.test.skip to turn use -P!testProfile to deactivate them and hence skipping them.
Another thought is that you could just do:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<skip>${maven.test.skip}</skip>
</configuration>
</plugin>
</plugins>
I haven't actually tried that... it should in theory work. I seem to remember that the <skip> configuration is on all plugins.
Just to clarify the Gareth David point:
When you run mvn ... -DskipTests, only the execution of tests is skipped. This is the same behavior if you run mvn ... -Dtest=notest
When you run mvn ... -Dmaven.skip.test=true, then both test execution and compilation are skipped.
So the second command is enough, without any modification of your pom.xml file.
(source)

Maven - Skip building test classes

Is there a simple way to not build the test classes?
mvn clean install -Dmaven.test.skip=true
According to the documentation on the Maven Surefire Plugin, -Dmaven.test.skip should skip both compilation and execution of the tests. By contrast, -DskipTests just skips the test execution: the tests are still compiled.
Just to be explicitly clear:
skipTests will compile anything in the <testSourceDirectory>, but will not execute them.
maven.test.skip will NOT compile any tests, but WILL execute any compiled tests that made their way into the <testOutputDirectory>.
So the behavior of the above 2 is opposite. Just wanted to point out that maven.test.skip doesn't skip compilation AND execution if test files are unpacked/copied/etc. into <testOutputDirectory>.
Also, depending on which version of Maven your using, there's also maven.test.skip.exec=true which additionally skips test execution similar to skipTests.
Run a phase that doesn't include test-compile, for example compile.
mvn clean compile
I'm not an expert at maven, but what I use in my current project is:
mvn clean install -DskipTests=true
Depending on your use case using:
mvn compile -DskipTests=true
might work for you too.
I found a work-around in another question, which actually overrides a plugin execution by adding the following snippet in your pom.xml by default:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
This seems to work but definitely does not disable phase but disables the default actions that a plugin defines at a specific phase.

Combined site/deploy goal for Maven

When running a Maven build on the CI server, I generate the site to publish the documentation and reports, and also deploy the artifact to the snapshot repository for use by other projects. To do this I run the following goals:
mvn clean site deploy
This means the unit tests are run twice, once for the site lifecycle and once for the deploy lifecycle. If I configure the site goal to be bound to the standard lifecycle the tests are still run twice, running the site goal always causes the tests to be run because of the #requiresDependencyResolution test annotation. This is fine if you're only creating the site, but in the context of a deploy it greatly increases the build time for no benefit.
I have a workaround that involves copying the SiteMojo (and the required parents) to a new plugin and removing the #requiresDependencyResolution test annotation from the copy.
This modified mojo will generate the reports without forcing the tests to be run again but I'd prefer a solution that doesn't involve any hacking of the site plugin. Is there a way to suppress the requiresDependencyResolution annotation?
I'm surprised this works - the #requiresDependencyResolution test tag doesn't actually trigger the tests being built - that should be one of the reports that you've included. Normally, I recommend running the site and the build in separate Maven executions in CI so you can get fast feedback on your build and publish the latest site only when that succeeds.
Another alternative is to run it as mvn clean deploy site, and choose the report-only mojo for surefire-report-maven-plugin (this is usually the report that is running the tests again). This will use the previous test results. Of course, another alternative is disabling that report altogether, since you likely get those results from another source such as your CI server anyway.
My current approach is to create a new plugin with copies of the relevant types from the maven-site-plugin. These types are identical to the standard versions except for changing the type name, the goal name and the removal of the #requiresDependencyResolution test annotation.
The copied types are:
org.apache.maven.plugins.site.AbstractSiteMojo
org.apache.maven.plugins.site.AbstractSiteRenderingMojo
The parent mojos are required so Maven can process the javadoc-based annotations (this shouldn't be required for Maven 2.2.0+).
org.apache.maven.plugins.site.SiteMojo
org.apache.maven.plugins.site.SiteJarMojo
These two are copied as SiteOnlyMojo and SiteJarOnlyMojo respectively, SiteJarOnlyMojo is changed to inherit from SiteOnlyMojo . Otherwise the only changes are to change the goal namess and remove the annotation.
So SiteOnlyMojo has:
* #goal site
* #requiresDependencyResolution test
changed to:
* #goal site-only
and SiteJarOnlyMojo has:
* #goal jar
* #phase package
changed to:
* #goal jar-only
* #phase package
These types are declared in a maven-plugin project with artifactId maven-site-only-plugin with a dependency declared on the proper site plugin.
To use this I define a profile (I don't want the reports running on every execution, only when -Psite is declared on the command line) and bind it to the prepare-package phase (prior to 2.1.0, you'd have to bind it to the package phase instead).
<profile>
<id>site</id>
<build>
<plugins>
<plugin>
<artifactId>maven-site-only-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>jar-only</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<build>
<pluginManagement>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.2</version>
<executions>
<execution>
<goals>
<goal>site</goal>
<goal>deploy</goal>
</goals>
<phase>deploy</phase>
</execution>
</executions>
</plugin>
...
</plugins>
</pluginManagement>
</build>
This will automatically execute the site action when issuing a 'mvn deploy' command, as well as ensuring the testing suite is only executed once.