Maven war packaging skipped prior to tests being run - maven

I have a maven project which has some Selenium based integration tests to run in a package called sit. I have configured the failsafe plugin to include test files in the package eg. <include>sit/**/*Test.java</include>.
I am trying to run mvn clean install and when it launches the tests I noticed it hasn't actually run the maven-war-plugin i.e. not packaged it into a war prior to running the tests. If however I run mvn clean install -Dmaven.test.skip=true then it does successfully package the war. (I also have the cargo plugin configured to deploy the war which is how I noticed there was an issue as it fails to deploy a non existing war)
The structure of my pom is similar to the below
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>a</groupId>
<artifactId>a</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<includes>
<include>sit/**/*Test.java</include>
</includes>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Any ideas why it doesn't run the war plugin without setting -Dmaven.test.skip=true?
It does in both scenarios create the class files

Try to rename your test classes for integration tests to be with an *IT.java suffix (or prefix...), since this is the convention for tests to be run by maven-failsafe-plugin.
The *Test.java is another convention for running the tests by maven-surefire-plugin.
So no need to exclude them, just rename it.

Ok it seems the issue was maven-surefire was trying to run the integration tests as unit tests, so we have to explicitly exclude the integration tests from surefires unit tests
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
...
<configuration>
<excludes>
<exclude>sit/**/*Test.java</exclude>
</excludes>
</configuration>
</plugin>

Related

is there any way to skip cucumber scenarios while running unit steps?

mvn install is running cucumber steps also. in our local development, we need to run only unit tests and not the cucumber scenarios. Tried with -Dtest=!com.mycompany.* no luck.
And at the same time, we need to skip our Unit Tests while executing a cucumber scenario, is that possible?
This could be achieved by using build profiles. You should run your unit tests by using the surefire plugin and the cucumber scenarios with the failsafe plugin. Naming conventions for automatic running of tests for surefire and failsafe.
<profiles>
<profile>
<id>jenkins</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<excludes>
<exclude>**/*Test.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M3</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Run this with mvn clean install -Pjenkins. This will only run the integration tests ie scenarios.
To run the unit tests just use mvn clean install. Surefire is invoked ie unit test, by default but not failsafe.

Regarding updating pom file

I am working on a continuous integration tool and here i need to integrate jacoco plugin after checking out. I do not want to enforce developer to add jacoco plugin while checkin instead i would like to add it while running the jenkins based continuous integration tool.
Is it possible to achieve any of these options?:
1. to modify the pom file checked in by the developer and inject the dependency and plugin required for jacoco?
OR
to add the jacoco plugin super pom and mention that in jenkins configuration.
I tried this super pom approach, and it was reading super pom from a common repository, but not generating jacoco-exec file. I used below in super pom.
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
pom
<dependencies>
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.6.201602180812</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.6.201602180812</version>
<configuration>
<destFile>${basedir}/target/jacoco-unit.exec</destFile>
<dataFile>${basedir}/target/jacoco-unit.exec</dataFile>
</configuration>
<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>
Any help will be appreciated. Thanks
You can create a separate profile in the pom.xml, name it as jenkins profile and include jacoco plugin in that profile. You can then configure the mvn command in your jenkins job to include -P jenkins_profile_name. So the build would be done using the jenkins profile configuration.
Mark the existing profile as default and developers won't need to do anything specific.
For more details, refer to maven documentation for build profiles:
http://maven.apache.org/guides/introduction/introduction-to-profiles.html

Sonar: measuring code coverage when integration tests are in a different project

Having following Maven project structure:
-project1 <-- parent pom with two children.
|--module1 <-- web services
\--module1-itest <-- integration tests written with TestNG
What we do today:
Run mvn sonar:sonar in module1, which shows code coverage from
the Unit tests in Sonar's dashboard.
Run mvn jetty:run on module1, and immediately after that run mvn test on module1-itests to test it.
I know this is far from the ideal scenario... it's more like an intermediate step while we try to improve a legacy project with almost no tests at all...
My question is: what would be the best way to get the code coverage done by the execution of the integration tests in Sonar's dashboard of module1?
Initially, I'm inclined to move the code in module1-itest to module1, and run them using the Failsafe plugin and the well-documented integration with JaCoCo. In this way, Module1 will have a mix of JUnit unit tests and TestNG integration tests, each group to be run by Surefire and Failsafe, respectively, starting up a Jetty server in the pre-integration phase.
However, we have reasons to keep both projects separated, so I'm wondering:
Is the approach above a good one?
Is there any other recommended way we can use to keep both projects separated, but including the code coverage done by module1-itest in module1 Sonar's dashboard?
Thanks,
This is how we solved it:
Summary:
Service and Service-itest projects are two independent modules.
Service has unit tests which coverage is reported by Sonar.
Service-itests uses Cargo to load the service WAR and run the integration tests. The code coverage collected in this execution is reported one level above. In this way, the coverage for the ITests is collected and merged cross-module and reported at the parent project pom level. We also like this approach becasue it allows us to have different ITests projects (for example, one with Cargo loading the app and another using JBehave), and they can evolve independently.
In the parent pom:
<modules>
<module>service</module>
<module></module>
<module>service-itest</module>
</modules>
<!-- Sonar -->
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<!-- The destination file for the code coverage report has to be set to
the same value in the parent pom and in each module pom. Then JaCoCo will
add up information in the same report, so that, it will give the cross-module
code coverage. -->
<sonar.jacoco.itReportPath>${project.basedir}/../target/jacoco-itests.exec</sonar.jacoco.itReportPath>
...
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.6.3.201306030806</version>
</plugin>
</plugins>
</pluginManagement>
...
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<includes>
<include>our.project.packages.*</include>
</includes>
</configuration>
<executions>
<execution>
<id>pre-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
And in the pom.xml file of the -itest project:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<!-- The destination file for the code coverage report has to be set
to the same value in the parent pom and in each module pom. Then JaCoCo will
add up information in the same report, so that, it will give the cross-module
code coverage. -->
<destFile>${project.basedir}/../target/jacoco-itests.exec</destFile>
<includes>
<include>our.packages.*</include>
</includes>
</configuration>
<executions>
<execution>
<id>post-test</id>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<skip>${cargo.skip}</skip>
<container>
<containerId>jetty7x</containerId>
<artifactInstaller>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-distribution</artifactId>
<version>7.6.12.v20130726</version>
<type>zip</type>
</artifactInstaller>
</container>
<configuration>
<type>standalone</type>
<properties>
<cargo.servlet.port>${jetty.port}</cargo.servlet.port>
<cargo.jvmargs>${argLine}</cargo.jvmargs>
</properties>
<deployables>
<deployable>
<artifactId>pam_filetask_manager_service</artifactId>
<groupId>${project.groupId}</groupId>
<type>war</type>
<pingURL>http://server:22000/ping</pingURL>
<properties>
</properties>
</deployable>
</deployables>
</configuration>
</configuration>
<executions>
<execution>
<id>start-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>install</goal>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-server</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>

maven failsafe plugin

I am trying to run only selenium tests using mvn failsafe plugin. I created a separate profile to run only the selenium tests but mvn is not able to find them. my project structure looks like
moduleA
scr/main/...
src/test/integration/java/...
scr/test/unit/java/...
moduleB
scr/main/...
src/test/integration/java/...
scr/test/unit/java/...
moduleC (only for selenium tests)
scr/main/java/com/selenium/A.java
src/test/java/...
Since I have new directories for the unit and integration tests in moduleA and B. I have defined the following in pom.xml (listingB) to let Maven know about the additional test directories. So far so good but when I add selenium tests in moduleC and I want to run only selenium its not running selenium tests. I created a new profile (listingA) to run selenium tests. Any help is appreciated.
listingA:
<profiles>
<profile>
<id>selenium</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<id>verify</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>**/selenium/*.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
listinB:
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/src/test/unit/java</source>
<source>${basedir}/src/test/integration/java</source>
<source>${basedir}/src/test/common/java</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-test-resource</id>
<phase>generate-test-resources</phase>
<goals>
<goal>add-test-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${basedir}/src/test/integration/resources</directory>
<directory>${basedir}/src/test/unit/resources</directory>
<directory>${basedir}/src/test/common/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
The first thing which came into my mind is why you are separating the unit- and integration tests by using a different folder, cause in Maven the separation between unit- and integration tests is done by naming convention.
The unit tests have to be named like
**/Test*.java
**/*Test.java
**/*TestCase.java
The integration test have to be named like:
**/IT*.java
**/*IT.java
**/*ITCase.java
This means in other words you can put your integration tests and your unit tests into the same folder which is src/test/java without any problem. The execution of the integration tests is not influenced by this.
If you would call
mvn clean package
only the unit tests will be run. If you need to run the integration tests as well you can simply use:
mvn verify
If you wan't to skip the unit tests you can use the following:
mvn -DskipTests=true verify
For the separate selenium module which you have created the best solutin is to put the integration tests into the usual folder src/test/java with the appropriate naming convention.
The problem you might have is if your integration tests needed some special resources you might move those integration tests into the separate module with integration tests only.
If your Selenium tests are in the src/test/java folder, delete the <includes> parameter from the configuration of maven-failsafe-plugin in listingA
Name your Selenium test classes like:
**/IT*.java
**/*IT.java
**/*ITCase.java
(as khmarbaise has suggested)
Failsafe runs integration tests using Surefire, therefore don't name your Selenium test classes like:
**/Test*.java
**/*Test.java
**/*TestCase.java
because this will make them run in test fase and not in integration-test fase as you plan.
I have a configuration similar to yours and it works.

Maven is not using failsafe plugin for integration tests

When I run mvn clean install, for the integration-test phase it does not use the failsafe plugin.
However if i explicilty call the plugin to run the integration test, it works (mvn failsafe:integration-test).
How can I make maven use the failsafe plugin when I run mvn clean install during the integration-test phase?
Quote from official documentation:
To use the Failsafe Plugin, you need to add the following configuration
to your pom.xml
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.11</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
Is this what you looking for?

Resources