How to defer Maven test goal after deployment? - maven

I'm using the JBoss and WildFly Maven plugin to deploy my applications.
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>1.0.0.Beta1</version>
</plugin>
</plugins>
The problem that I have found is that if I have some Junit test in my project they are executed before application deployment, leading to a test with an inconsistent application state. Is it possible to configure somehow this plugin to kick-in before the test phase ?
Thanks

This plugin by default executes alongside the package phase and you'll probably have issues attempting to run the plugin before your application is packaged. As an alternative, you could override the maven-surefire-plugin to run your tests in a later phase, such as integration-test, which would be executed after your application has been packaged.

A practical example can be found on this Maven tutorial where it's show how to include failsafe plugin and bind it to the executions of the integration-test and verify phase. This way tests which are engineered as integration test (e.g ending in *IT) will execute only during the integration-test phase.

Related

Execute application using mvn clean install

I am working on a simple spring boot application (created from spring initializr contains web mega-dependency).
I added also Cucumber dependencies for acceptance test.
When I run mvn clean install it runs directly the cucumber test, but me I want to run the app before tests (And why not stop the app after the tests terminate).
I tried maven exec plugin but it does not work:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions><execution>
<goals><goal>java</goal></goals>
</execution></executions>
<configuration>
<mainClass>org.dhappy.test.NeoTraverse</mainClass>
</configuration>
</plugin>
Skipping tests
If there is a need to skip tests and just compile and package the application, you can set the skipTests property as follows:
mvn install -DskipTests
Application execution
If you want to run the application, you can use the exec plugin. There are two flavours ("goals" really): one runs the package application and the other runs a Java class. If you know the class name, you can run that plugin as follows:
mvn exec:java -Dexec.mainClass="org.dhappy.test.NeoTraverse"
Integration testing
Finally, if you want to run the application first before you can run the tests, you are actually not doing unit testing. Your tests in this case are perhaps integration and not unit tests. The actual details would vary depending on whether your application has complex needs such as a database and a web server.
Integration testing happens at a different "phase" in maven lifecycle.
In short, you need to rename your Java test classes something other than *Test.java so that maven surefire plugin ignores your tests. You then need to include maven-failsafe-plugin so that integration testing happens.
You want to perform these steps:
Start the application
Run a set of tests
Stop the application
Starting and stopping the application is one thing and could be done in the <phase>pre-integration-test</phase> and <phase>post-integration-test</phase>. Integration testing is done in the <phase>integration-test</phase>
You want to read and understand https://maven.apache.org/surefire/maven-failsafe-plugin/usage.html. Specifically, look at the Using jetty and maven-failsafe-plugin example.

Sharing common Springboot integration tests with jar?

Can I have a jar containing Springboot integration tests & use this jar in other modules to execute the common integration tests?
As stated here:
Maven projects already define a standard for a project's tests. And in
my opinion it doesn't make sense to make a project dependent on its
tests--if anything, tests would be dependent on the module under test,
since tests use the module, but not vice-versa.
Though if you wish to do this anyway, to answer your question: yes it is possible. As described here:
There is a new way of running a test in Maven from another jar. from
maven-surefire-plugin version 2.15 you can tell Maven to scan your
test jars for tests and run them. You don't need to extract the tests
jar. Just add a dependency to your test jar like so:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<dependenciesToScan>
<dependency>test.jar.group:test.jar.artifact.id</dependency>
</dependenciesToScan>
</configuration>
</plugin>

Maven skip specific test [duplicate]

In my maven project I have a number of modules. Is it possible to turn off running unit test for some modules via command line options?
My project takes about 15 mins to run through all unit tests. I would like to speed up the overall build by running just the unit tests in the module I am working on. I do not want to go in and edit each individual pom.xml to achieve this.
I have tried a solution outlined here: Can I run a specific testng test group via maven? However the result is a lot of test failures in modules that I want to skip. I suppose 'group' is not the same concept of module?
To toggle unit tests on and off for an entire project use Maven Surefire Plugin's capability of skipping tests. There is a drawback with using skipTests from the command line. In a multi-module build scenario, this would disable all tests across all modules.
If you need more fine grain control of running a subset of tests for a module, look into using the Maven Surefire Plugin's test inclusion and exclusion capabilities.
To allow for command-line overrides, make use of POM properties when configuring the Surefire Plugin. Take for example the following POM segment:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<configuration>
<excludes>
<exclude>${someModule.test.excludes}</exclude>
</excludes>
<includes>
<include>${someModule.test.includes}</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<someModule.skip.tests>false</someModule.skip.tests>
<skipTests>${someModule.skip.tests}</skipTests>
<someModule.test.includes>**/*Test.java</someModule.test.includes>
<someModule.test.excludes>**/*Test.java.bogus</someModule.test.excludes>
</properties>
With a POM like the above you can execute tests in a variety of ways.
Run all tests (the above configuration includes all **/*Test.java test source files)
mvn test
Skip all tests across all modules
mvn -DskipTests=true test
Skip all tests for a particular module
mvn -DsomeModule.skip.tests=true test
Only run certain tests for a particular module (this example includes all **/*IncludeTest.java test source files)
mvn -DsomeModule.test.includes="**/*IncludeTest.java" test
Exclude certain tests for a particular module (this example excludes all **/*ExcludeTest.java source files)
mvn -DsomeModule.test.excludes="**/*ExcludeTest.java" test
Found a way to exclude on command line:
# Exclude one test class, by using the explanation mark (!)
mvn test -Dtest=!LegacyTest
# Exclude one test method
mvn verify -Dtest=!LegacyTest#testFoo
# Exclude two test methods
mvn verify -Dtest=!LegacyTest#testFoo+testBar
# Exclude a package with a wildcard (*)
mvn test -Dtest=!com.mycompany.app.Legacy*
This is from: https://blog.jdriven.com/2017/10/run-one-or-exclude-one-test-with-maven/
…and if you like to pass the parameter to maven release plugin in Hudson/Jenkins you have to use
-Darguments=-DskipTests
to get it work.
If you want to use Maven profiles:
http://maven.apache.org/guides/introduction/introduction-to-profiles.html
you might want to make it work doing something like this:
Skipping tests in some modules in Maven
I don't know if there is a supported command line option that does the same.
You also might try using environment properties directly, something as per this doc page:
http://maven.apache.org/plugins/maven-surefire-plugin/examples/skipping-test.html
i.e. something like:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<skipTests>${moduleA.skipTests}</skipTests>
</configuration>
</plugin>
then using mvn -DmoduleA.skipTests=false test to test that one module.

Make maven run one task before another when running a single plugin

I've got a project set up using the Maven Cargo plugin to launch Tomcat with my webapp deployed in it, along with some other webapps that are needed for support. This works great. Unfortunately, when I run "mvn cargo:run" it doesn't do a build first, but instead just actually starts Tomcat running the code the last time I did do a build.
Previously I used the tomcat7 plugin instead, and that did do a build first and always ran the current version of the source code. As such, I could change my code and run "mvn tomcat7:run" and know that the code changes had been built and were running.
I can't find any way with the Cargo plugin to make it do this, but is there some way with Maven to make it at least run the Package phase when I run a specific plugin so that it will build the WAR file correctly first?
The Tomcat plugin automatically invokes the compile phase prior to executing itself. The Cargo plugin won't do that. In order to compile your code before executing the plugin, you need to run
mvn clean compile cargo:run
If you want to start and stop the container automatically before and after your integration tests, you can also bind cargo:start and cargo:stop to Maven's lifecycle phases. See Automatically executing and stopping the container when running mvn install for details.
Here is a full example how to integrate the start via Cargo in the usual build. https://github.com/khmarbaise/maui/tree/master/src/main/resources/it-example-container. You can start the integration tests via mvn -Prun-its clean verify which might be better
A completely different approach would be to use the exec-maven-plugin to execute multiple goals with one command:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<executable>mvn</executable>
<arguments>
<argument>clean</argument>
<argument>compile</argument>
<argument>cargo:run</argument>
</arguments>
</configuration>
</plugin>
<!-- more plugins... -->
</plugins>
</build>
This way, you would only have to call
mvn exec:exec
to clean, compile and run your application.

Why failsafe plugin requires both integration-test and verify goals?

I have the next pom.xml
<project>
...
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<argLine>${failsafeArgLine}</argLine>
<includes>
<include>**/dmg/*IT.java</include>
</includes>
<skipTests>${skipTests}</skipTests>
</configuration>
</execution>
</executions>
</plugin>
...
</project>
The problem is that when I'm taking off verify goal then the build is every time successful even if there was test failures.
And when I'm Taking off integration-test goal the integration tests simply do not run
Why failsafe plugin requires both integration-test and verify goals?
In Maven Failsafe plugin reference you can find simple answer why build is always successful
failsafe:integration-test runs the integration tests of an application.
failsafe:verify verifies that the integration tests of an application passed.
Without verify goal test results are not checked at all(but they are executed), so failsafe plugin requires integration-test goal to run tests, and verify to "verify" their results.
In Maven there are two types of test runner plug-ins, Surefire and Failsafe and they both serve different purposes. (I mention Surefire here because I feel it helps explain and contrast different types of failure in builds.)
Surefire
Surefire is a plug-in designed for your pre-deploy tests, such as Unit and Component tests. Surefire is guaranteed to return a failure (and therefore break your build) if any of the tests fail.
You want this behaviour in pre-deploy tests because you want to fail the build early if your tests fail, and as Unit and Component tests don't (or shouldn't) have any external dependencies it's safe to fail a build there and then.
Failsafe
Failsafe is a plug-in designed for post-deploy tests, such as Functional and Smoke tests.
Failsafe, as the name implies handles failures safely, by always returning a success exit code (as you have experienced in your build).
The reason behind this is for post-deploy tests you don't want test failures to immediately break the build because you may have spun up infrastructure, or seeded some test data into the system, which needs clean-up before the build is failed.
Therefore Failsafe splits the failure checking into the failsafe:verify goal which happens in the verify phase.
If you run Maven without parameters (assuming the normal jar lifecycle) you'll notice a phase between integration-test and verify called, post-integration-test. This is the phase which was designed for the tear down of any infrastructure or test data you may have injected into the system to run the tests.
... pre-integration-test, integration-test, post-integration-test, verify, ...
The phase before integration-test, pre-integration-test is designed for the said seeding and infrastructure creation.
To sum it all up, with pre-deploy tests you want to fail the build as early as possible, and so surefire guarantees this by exiting with a failure.
Whereas with post-deploy tests there are often external dependencies which need clean-up before you fail the build. For example in Kubernetes you may want to issue a rollback of the deploy and so failsafe:integration always returns a build success to guarantee you can perform the clean-up before failing the build by checking the status with failsafe:verify.
(The currently accepted answer just quotes the manual and doesn't explain why there are two commands and there are differences which is why I feel this answer is needed.)

Resources