Tom is a passionate Java/JEE developer working remotely from home located in Poland. He is a big fan of Apache Wicket, clean code, testing and methods with names that actually say something. In his free time he blogs, tweets and organizes Confitura, the biggest Java conference in Poland. Privately husband, father and dog owner, he likes to watch and play football (soccer if you're from USA). Tomasz is a DZone MVB and is not an employee of DZone and has posted 15 posts at DZone. You can read more from them at their website. View Full User Profile

Running Unit Tests and Integration Tests Separately With Maven Failsafe and TestNG

01.24.2013
| 5228 views |
  • submit to reddit

Recently for my new pet project I decided that I would like to have some tests executed during standard mvn test and some other ones only during different phase, let’s call it integration phase. I googled and googled and nothing seemed to work, so after struggling with making my setup work I’ve decided to write down my findings how I was able to configure TestNG with Maven to run integration and unit tests separately.

Basic (not working) setup

For integration testing there is a Maven Failsafe plugin that is supposed to do what we want out of the box. Unfortunately, things are not as easy and straightforward as we might expect.

Let’s look at basic setup that should work:

We have two test classes, one with IT postfix that will indicate that this is our integration test:

import org.testng.annotations.Test;
 
import static org.fest.assertions.Assertions.assertThat;
 
public class ExampleUnitTest {
 
    @Test
    public void shouldPass() {
        assertThat(false).isFalse();
    }
}

and

import org.testng.annotations.Test;
 
import static org.fest.assertions.Assertions.assertThat;
 
public class StatusTestIT {
 
    @Test
    public void shouldFail() {
        assertThat("aaa").isEqualTo("");
    }
}

and now let’s declare plugin mentioned above in our pom.xml:

<project>
     
    <!-- ... -->
    <build>
        <plugins>
            <!-- ... -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.9</version>
            </plugin>
 
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.13</version>
                <configuration>
                    <includes>
                        <include>**/*IT.java</include>
                    </includes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

After that we should see two things. mvn test should pass as we have a one green test in ExampleUnitTest class, but mvn failsafe:integration-test should fail with StatusTestIT red. But as I said before, this does not work. mvn test looks as expected, but second Maven execution is passing as well showing that no test were run. Plugin seems to omit our completely valid test…

Small fix doing its job

After testing different approaches I found out that all we need to make this setup work is to add plugin execution to an integration-test phase of maven life cycle. So tiny change, but now our integration tests are executed only when we call mvn integration-test.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.13</version>
    <configuration>
        <includes>
            <include>**/*IT.java</include>
        </includes>
    </configuration>
    <executions>
        <execution>
            <id>failsafe-integration-tests</id>
            <phase>integration-test</phase>
            <goals>
                <goal>integration-test</goal>
            </goals>
        </execution>
    </executions>
</plugin>

And that’s all, we could execute integration tests only when we really want to. Of course there are some things to remember when adopting setup described above:

  • our unit tests must have Test postfix, if you use something else, we have to configure surefire plugin using include
  • during integration test unit tests are executed too. This is a small flaw in this setup, but exclude **/*Test.java seem not to work :(

Source code of this example setup is available on GitHub





 

Published at DZone with permission of Tomasz Dziurko, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Vijay Nathani replied on Sat, 2013/01/26 - 4:48am

I use the below mentioned configuration. There is no need to include sure-fire plugin separately. "mvn test" runs the unit tests. "mvn allTests" runs all the tests.

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>2.12</version>
        <executions>
          <execution>
            <goals>
              <goal>allTests</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

Ben Wu replied on Sat, 2013/02/02 - 8:44am

I tried the "Basic (not working) Setup" and found that it was working if you run it in this order: First, run "mvn clean test" to make all unit tests (with Test postfix) run. Second, run "mvn failsafe:integration-test" and the integration tests (with IT postfix) got run successfully. But if you don't run "mvn clean test" at first and run "mvn clean failsafe:integration-test" instead, no integration tests got run.

Tomasz Dziurko replied on Sat, 2013/02/02 - 1:01pm in response to: Ben Wu

I tried to repeat steps you mentioned and surprisingly, you are right. List of executed tests depends on order of Maven commands. Nice feature :)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.