Maven plugin crossed execution order - maven

I'm writing some integration tests using failsafe plugin.
I want to execute the following:
1) Start Docker (goal start in phase pre-integration-test)
2) Start Spring (goal start in phase pre-integration-test)
3) Tests (phase integration-test)
4) Stop Spring (goal stop in post-integration-test)
5) Stop Docker (goal stop in post-integration-test)
Why? I want to start Docker BEFORE Spring so all databases are ready when Spring boots and also I want to stop Docker AFTER Spring to avoid a lot of errors in Spring due to database connection losses.
I have the following pom.xml:
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.20.1</version>
<executions>
<execution>
<id>run-docker-containers</id>
<goals>
<goal>start</goal>
</goals>
<configuration>
...
</configuration>
</execution>
<execution>
<id>stop-docker-containers</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>pre-integration-test</id>
<goals>
<goal>start</goal>
</goals>
<configuration>
...
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
But with this pom.xml I'm getting this order:
1) Start Docker
2) Start Spring
3) Tests
4) Stop Docker
5) Stop Spring
This is, Docker is stopped BEFORE Spring and I don't want that.
I know that the execution order in Maven is given by the order in pom.xml, but in this case I need to have crossed goals.
Any advice?
Thanks.

Execution order in Maven is based on two components:
First, the lifecycle phase to which the execution is bound
For executions bound to the same phase, the ordering in the POM takes precedence.
Maven doesn't allow the same plugin to be configured twice, so it's not possible to move the Docker Stop execution below Spring. The only way I know to fix things like this is to introduce a third phase into the mix. It looks a bit weird to bind 'stop' goals to the verify phase, and I'd definitely add comments to explain why this was done for posterity - but it works.
This plugin config does the following (assuming you use the maven-failsafe-plugin for integration tests; if you use a different plugin follow the same principles with that plugin). Maven lifecycle phase in parentheses:
1) Docker Start (pre-integration-test)
2) Spring Start (pre-integration-test; Spring plugin config after Docker)
3) Execute tests (integration-test)
4) Spring Stop (post-integration-test)
5) Docker Stop (verify)
6) Verify test results (verify; Failsafe plugin config after Docker)
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.20.1</version>
<executions>
<execution>
<id>run-docker-containers</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-docker-containers</id>
<phase>verify</phase> <!-- important: note phase -->
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${version.maven.failsafe.plugin}</version>
<executions>
<execution>
<id>failsafe-integration-tests</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>failsafe-verify</id>
<phase>verify</phase>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>pre-integration-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>

Related

Make Integraton Test cover all submodules

I do searched for similar topics. But mine issue is different.
The background is that I've got an single spring boot project, and it became bigger and bigger. Then I split it into serveral modules following the guide from spring Spring boot - Creating a Multi Module Project.
Let's say, now I've got 2 projects: Web and ServiceLayer. All my previous integration test are in Web now, and it looks like that from sonar I can only see the coverage of proejct-web.
I am using jacoco maven plugin and here is the maven pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<showSuccess>false</showSuccess>
</configuration>
</plugin>
<!-- JaCoCo configuration -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5.201505241946</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
How to configure and make the coverage of submodules available on sonar?
Thanks!
You can add the destFile tag after your goals tag
Something like this
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.8</version>
<configuration>
<append>true</append>
</configuration>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.basedir}/../target/jacoco.exec</destFile>
</configuration>
</execution>
<execution>
<id>default-report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
This will aggregrate all the results in each of the modules into a file.

Command line mvn parameter to stop spring-boot-maven-plugin from executing run

I'm developing a Spring Boot application and as part of the Integration Test phase of my maven project, I have configured the spring-boot maven plugin to start up and shut down during the pre and post integration test parts of the build as follows:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>pre-integration-test</id>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>post-integration-test</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
However, I did this just so that my developers can run their tests against a local instance of the service. On Jenkins, I would run the tests against an external service where I had deployed the service and I do not need the Spring Boot application to be spun up within the Jenkins job.
Is there a way for me to explicitly stop the spring-boot maven plugin from starting up the service via a mvn command line override?
Sure, you can expose a property for it, something like
<properties>
<skip.it>false</skip.it>
</properties>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>pre-integration-test</id>
<goals>
<goal>start</goal>
</goals>
<configuration>
<skip>${skip.it}</skip>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<goals>
<goal>stop</goal>
</goals>
<configuration>
<skip>${skip.it}</skip>
</configuration>
</execution>
</executions>
</plugin>
Once you have that, run your command as follows: mvn verify -Dskip.it=true and the Spring Boot application will not be started as part of your integration tests.

Inegration test using maven

I am trying to create something like integration tests - i am using groovy to send requests and to parse answers. I'd also want starting of jboss and deploying of .ear to be automatically. Using cargo plugin i was able to start jboss. By using exec plugin i am trying to execute perl script that puts ear to deploy folder. Next phase - execute groovy tests, but this phase starts without waiting for ear to be deployed. Is it possible to make phase to wait for server to be deployed to jboss? My pom:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<executions>
<execution>
<id>unpack-application-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>${basedir}/src/main/script/appserver/unzip.groovy</source>
<defaults>
<installDirectory>${appserver.install.directory}</installDirectory>
<zipUrl>${appserver.zip.url}</zipUrl>
</defaults>
</configuration>
</execution>
<execution>
<id>prepare-application-server-configs</id>
<phase>pre-integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>${basedir}/src/main/script/appserver/${suffix}/postUnzipAction.groovy</source>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
</executions>
<configuration>
<wait>false</wait>
<container>
<containerId>${appserver.id}</containerId>
<home>${appserver.home}</home>
<timeout>6000000</timeout> <!--in ms-->
</container>
<configuration>
<properties>
<cargo.servlet.port>${servlet.port}</cargo.servlet.port>
<cargo.rmi.port>${rmi.port}</cargo.rmi.port>
<!-- corresponds to -Djboss.bind.address=0.0.0.0 under jboss -->
<cargo.hostname>0.0.0.0</cargo.hostname>
</properties>
</configuration>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>deploy-with-script</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>perl</executable>
<workingDirectory>.</workingDirectory>
<commandlineArgs>${deploy.pl.cmd} -x redeploy</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
setup and tear down your server before and after integration test phase, something like that:
<executions>
<execution>
<id>start-tomcat</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>stop-tomcat</id>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
Rename your unit tests to be skipped by surefire but executed by maven-failsave-plugin to *IT.java: http://maven.apache.org/surefire/maven-failsafe-plugin/examples/inclusion-exclusion.html

How do include JUnit test cases as a part of Maven build?

I have existing JUnit4 test cases which I run from Eclipse and as a part of Maven. Now I am looking to perform stress tests by leveraging them. I noticed Maven is not packaging them as a part of the build. How do I go about it?
This will attach the tests (and their sources) in a separate jar:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
<execution>
<id>attach-test-sources</id>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>test-jar</id>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
Afterwards you can use them as a dependency by using the type test-jar.

Maven - determine order of different plugin goals in the same phase

The following snippet is an excerpt of the configuration of the maven-cargo plugin, but the question is independent from that specific plugin.
<executions>
<execution>
<id>start</id>
<phase>pre-integration-test</phase>
<goals>
<goal>deploy</goal>
<goal>start</goal>
</goals>
</execution>
</executions>
This configuration (lets simply call it plugin A) will wait till pre-integration-test phase, then fire its goals deploy and start (in that order).
Say I have another plugin B which is relevant in the same phase. What are my options to
execute plugin B's goals before (after) A? (someStuff - > deploy -> start)
execute plugin B's goals in-between plugin A's goals (deploy -> someStuff -> start)
I figure that the answer to (1) is here, linking the order of the goals to the order of the plugin definition in the POM. But I have no idea about (2).
You are right about (1). If two plugins are to be executed on the same phase, then they will be executed in the order they are declared in pom.xml.
I'm not 100% sure about the (2), but I think it's impossible without some hacks, like using exec-maven-plugin, for example:
<!-- deploy -->
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<executions>
<execution>
<id>deploy</id>
<phase>pre-integration-test</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- do something -->
<plugin>
<groupId>some_other_plugin</groupId>
<artifactId>some_other_plugin</artifactId>
<executions>
<execution>
<id>someStuff</id>
<phase>pre-integration-test</phase>
<goals>
<goal>some_goal</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- start -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>start</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>mvn</executable>
<commandlineArgs>org.codehaus.cargo:cargo-maven2-plugin:start -Dparam=value</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>

Resources