Maven Skip Tests Example
1. Introduction
In this example we will explore Maven capabilities to skip running/compiling unit tests during a project build. Although this is not a recommended option, sometimes we may want to speed up the overall build by skipping tests from running for a particular project, for some projects or for all our projects.
To run the examples in this article we will need a JDK environment, a text editor and Apache Maven 3 installed. You can use the documentation link to install Maven.
2. Prerequisites
Before going further, we will need a couple of projects to work with. Download the article files available at this link and extract the archive in a fairly accessible location because we will use a command line tool to navigate inside the projects folders. For all the following examples, we will use the A:\JavaCodeGeeks
path as the root and extract the article files inside the JavaCodeGeeks
folder.
After you extract the archive on your computer, you will see five Maven projects. Two of them (JUnit_UseCase_1
and JUnit_UseCase_2
) uses JUnit as a testing framework and another two projects (TestNG_UseCase_1
and TestNG_UseCase_2
) uses TestNG as a testing framework. The last project, called MyCompany
, is a multi-module Maven application whereof we will discuss later.
Now that we have something to work with, let’s get started!
3. Skip running/compiling tests during development
Let’s start with our first example, testing the JUnit_UseCase_1
application. To ensure that everything works fine, navigate inside the project root folder and hit mvn test
using a command line tool. This command will compile our java class, java test class and executes tests. You should see something like below as a result:
As you can see, the project was a successful build running also our two tests. To see what’s inside the project, check the .\JUnit_UseCase_1\src\main\java\com\jcg\examples\Calculator.java
main class and the .\JUnit_UseCase_1\src\test\java\com\jcg\examples\CalculatorTest.java
test class.
Now, let’s test the JUnit_UseCase_2
application by navigating inside the project root folder and hit mvn test
again using a command line tool. You should see something like below:
In this case, the project build is meant to fail inside our tests. To see the code behind, check the .\JUnit_UseCase_2\src\main\java\com\jcg\examples\Calculator.java
main class and the .\JUnit_UseCase_2\src\test\java\com\jcg\examples\CalculatorTest.java
test class.
Now, in order to skip testing and avoid a failure in the project build we have several options available:
- Using the
mvn test-compile
command, which will compile our tests, but won’t execute them
- Using the
mvn –DskipTests=true test
command, which will compile our tests, but won’t execute them
- Using the
mvn -Dmaven.test.skip.exec=true test
command, which will compile our tests, but won’t execute them
- Using the
mvn -Dmaven.test.skip=true test
command, which will skip both running and compiling the tests
Similarly, you can test the TestNG_UseCase_1
and TestNG_UseCase_2
applications. Just change JUnit_UseCase_1
with TestNG_UseCase_1
and JUnit_UseCase_2
with TestNG_UseCase_2
in the above examples.
4. Skip running/compiling tests when packaging a project
In the same way, your unit tests can be skipped when packaging a project, when we take our code, our classes and package it in a distributed format, a JAR for example, as you will see in the following examples. To summarize it, these are the options we can use:
mvn -DskipTests=true package
mvn -Dmaven.test.skip.exec=true package
mvn -Dmaven.test.skip=true package
You may ask yourself what really happens behind the scene, what gets generated/created in fact that a print-screen, as we saw in the previous section, can’t tell? For those seeking to learn more, let’s seek deeper.
Navigate inside the JUnit_UseCase_1
project root folder using a command line tool and hit the mvn clean package
command to clean previous builds and package the project. Now if we look inside the JUnit_UseCase_1\target
project folder, among other folders, we will see the project packaged in the JUnit_UseCase_1-1.0.jar
archive, since we tested earlier the same project and it was a successful build, the test-classes
folder that contains the test class compiled, and also a folder named surefire-reports
. If we go further and look inside this folder, there are two files generated by the Maven Surefire plugin:
com.jcg.examples.CalculatorTest.txt
, which contains something like:
------------------------------------------------------------------------------- Test set: com.jcg.examples.CalculatorTest ------------------------------------------------------------------------------- Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.223 sec
This is the same message highlighted in our first print-screen, in yellow.
TEST-com.jcg.examples.CalculatorTest.xml
, which contains something like:
<?xml version="1.0" encoding="UTF-8" ?> <testsuite tests="2" failures="0" name="com.jcg.examples.CalculatorTest" time="0.028" errors="0" skipped="0"> <properties> <property name="java.runtime.name" value="Java(TM) SE Runtime Environment"/> <property name="sun.boot.library.path" value="A:\Java\jdk1.8.0_60\jre\bin"/> ... // Other properties </properties> <testcase classname="com.jcg.examples.CalculatorTest" name="testAddition" time="0.028"/> <testcase classname="com.jcg.examples.CalculatorTest" name="testSubtraction" time="0"/> </testsuite>
Now, let’s test the JUnit_UseCase_2
project and hit the same mvn clean package
command. If we look inside the JUnit_UseCase_2\target
project folder, our test-classes
folder was generated but we don’t see a JUnit_UseCase_2-1.0.jar
archive because our tests will fail. Also, the content of the two files generated by the Maven Surefire plugin will be slightly different, as follows:
com.jcg.examples.CalculatorTest.txt
, which contains something like:
------------------------------------------------------------------------------- Test set: com.jcg.examples.CalculatorTest ------------------------------------------------------------------------------- Tests run: 2, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.24 sec <<< FAILURE! testAddition(com.jcg.examples.CalculatorTest) Time elapsed: 0.052 sec <<< FAILURE! java.lang.AssertionError: Result should be 8 ! expected: but was: at org.junit.Assert.fail(Assert.java:88) at org.junit.Assert.failNotEquals(Assert.java:834) ... testSubtraction(com.jcg.examples.CalculatorTest) Time elapsed: 0.005 sec <<< FAILURE! java.lang.AssertionError: Result should be 2 ! expected: but was: at org.junit.Assert.fail(Assert.java:88) at org.junit.Assert.failNotEquals(Assert.java:834) ...
This is the same message highlighted in our second print-screen, in red.
TEST-com.jcg.examples.CalculatorTest.xml
, which contains something like:
<?xml version="1.0" encoding="UTF-8" ?> <testsuite tests="2" failures="0" name="com.jcg.examples.CalculatorTest" time="0.028" errors="0" skipped="0"> <properties> <property name="java.runtime.name" value="Java(TM) SE Runtime Environment"/> <property name="sun.boot.library.path" value="A:\Java\jdk1.8.0_60\jre\bin"/> ... // Other properties </properties> <testcase classname="com.jcg.examples.CalculatorTest" name="testAddition" time="0.052"> <failure message="Result should be 8 ! expected:<8> but was:<9>" type="java.lang.AssertionError">java.lang.AssertionError: Result should be 8 ! expected:<8> but was:<9> at org.junit.Assert.fail(Assert.java:88) at org.junit.Assert.failNotEquals(Assert.java:834) ... </failure> </testcase> <testcase classname="com.jcg.examples.CalculatorTest" name="testSubtraction" time="0.005"> <failure message="Result should be 2 ! expected:<2> but was:<1>" type="java.lang.AssertionError">java.lang.AssertionError: Result should be 2 ! expected:<2> but was:<1> at org.junit.Assert.fail(Assert.java:88) at org.junit.Assert.failNotEquals(Assert.java:834) ... </failure> </testcase> </testsuite>
As you can see, the <testcase />
tags now contains the <failure />
message tag that holds the error message.
It’s time to skip our unit tests! Let’s explore the three use cases:
- Using the
mvn clean -DskipTests=true package
command
If we look in the JUnit_UseCase_2\target
project folder, the JUnit_UseCase_2-1.0.jar
archive was created, our test class was compiled and is present inside the test-classes
folder, and the surefire-reports
folder and all its content were skipped from being created.
- Using the
mvn clean -Dmaven.test.skip.exec=true package
command
If we look in the JUnit_UseCase_2\target
project folder, the JUnit_UseCase_2-1.0.jar
archive was created, our test class was compiled and is present inside the test-classes
folder, and the surefire-reports
folder and all its content were skipped from being created.
- Using the
mvn clean -Dmaven.test.skip=true package
command
If we look in the JUnit_UseCase_2\target
project folder, the JUnit_UseCase_2-1.0.jar
archive was created, our test class was NOT compiled and the test-classes
folder, the surefire-reports
folder and their contents were skipped from being created.
5. Skip running/compiling tests when installing a project in the local repository
Until now, we have learned what are the Maven options and commands for skipping a test during the development stage of our project and skipping a test when packaging a project. Now we may want to take the packaged project, the JAR archive in our case, and install it in our local repository. We can’t just hit mvn install
in a command line tool if we know that our tests are going to fail during the build, but we can still skip running/compiling our tests during this phase also, as you can see below. Of course, you need to navigate inside your project root folder using a command line tool and use:
mvn -DskipTests=true install
: will compile our tests, but won’t execute them, and install the generated artifact in your local repositorymvn -Dmaven.test.skip.exec=true install
: will compile our tests, but won’t execute them, and install the generated artifact in your local repositorymvn -Dmaven.test.skip=true install
: will skip both running and compiling the tests and install the generated artifact in your local repository
6. Skip running/compiling tests for particular modules in a multi-module application scenario
While reading this article, we have explored Maven capabilities for skipping tests for a single application, but what about skipping tests in a multi-module application? For this purpose we have the MyCompany
application to work with, which you extracted earlier. If you look inside the project root folder, you will see four applications or modules for our MyCompany
application, and a pom.xml
file in which we have defined three build profiles:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jcg.mycompany</groupId> <artifactId>MyCompany</artifactId> <packaging>pom</packaging> <version>1.0</version> <name>MyCompany</name> <url>http://www.javacodegeeks.com/</url> <profiles> <profile> <id>all</id> <activation> <activeByDefault>true</activeByDefault> </activation> <modules> <module>JUnit_UseCase_1</module> <module>JUnit_UseCase_2</module> <module>TestNG_UseCase_1</module> <module>TestNG_UseCase_2</module> </modules> </profile> ... // Other profiles skipped here </profiles> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> </project>
Deciding to use the Maven concept of a build profile gives us a fine control over testing, packaging or installing in our local repository, a multi-module project. For example, let’s make use of our first profile and see the result below:
- Using the
mvn -Pall -DskipTests=true test
command to skip the unit tests for all our modules, whereall
is the identifier of this build profile
As a note, we can also use the mvn –DskipTests=true test
command, since this profile is active by default, as specified in our pom.xml
file.
Going further, the next two build profiles defined in our pom.xml
file are listed below:
... <profile> <id>jUnit</id> <activation> <activeByDefault>false</activeByDefault> </activation> <modules> <module>JUnit_UseCase_1</module> <module>JUnit_UseCase_2</module> </modules> </profile> <profile> <id>testNG</id> <activation> <activeByDefault>false</activeByDefault> </activation> <modules> <module>TestNG_UseCase_1</module> <module>TestNG_UseCase_2</module> </modules> </profile> ...
The purpose of these two profiles is to allow us the flexibility to test, package or install only the modules that uses JUnit or only those that uses TestNG as a testing framework. For example:
- Using the
mvn -PjUnit -DskipTests=true test
command to skip the unit tests for ourJUnit_UseCase_1
andJUnit_UseCase_2
modules, wherejUnit
is the identifier of this build profile
Similarly, you can define your own build profiles to work with.
7. Conclusion
In this article we have explored Maven capabilities for speeding up the overall build by skipping unit tests from running for a particular project and for some modules or for all our modules in a multi-module Maven application.
You can download the full source code of this example here: MavenSkipTestsExample.zip.