The Maven Cookbook

7.4. Running Specific TestNG Test Groups

7.4. Running Specific TestNG Test Groups

7.4.1. Task

You want to configure the Maven Surefire plugin to run specific tests that are defined in a TestNG Test Suite XML descriptor.

7.4.2. Action

Consider a TestNG test class which contains five methods with the @Test annotation. Each method also configures the groups parameter. Four methods are in the "unit" group and one method is in the "integration" group. This might be a common situation for a project that contains different kinds of tests that are to be run during different times of the software development lifecycle. Very often, there is a set of tests that should be run every time a programmer makes a change to source code. There may also be a certain kind of test that can only be executed on a specific integration and testing machine, and there can be other tests which require too much time and resources to be associated with a developer's daily development cycle.

Here is the SeriousComponentTest with five annotated test methods:

package org.sonatype.mcookbook;

import org.testng.annotations.Test;

public class SeriousComponentTest {

  @Test(groups={"unit"})
  public void testSad() throws Exception {
    assert SeriousComponent.testSeriousness("SAD");
  }

  @Test(groups={"unit"})
  public void testSerious() throws Exception {
    assert SeriousComponent.testSeriousness("SERIOUS");
  }

  @Test(groups={"unit"})
  public void testCrazy() throws Exception {
    assert SeriousComponent.testSeriousness("CRAZY");
  }

  @Test(groups={"unit"})
  public void testFunny() throws Exception {
    assert !SeriousComponent.testSeriousness("FUNNY");
  }

  @Test(groups={"integration"})
  public void testLargeFile() throws Exception {
    String text = "TEST";
    // Imagine that this method contained some serious
    // code that loaded a 100k line text file and
    // tested each line.
    assert SeriousComponent.testSeriousness(text);
  }
}

The first four methods are executed quickly as unit tests, but the last method requires more time to execute, and if going to be run periodically by a continuous integration server like Hudson. To make the development cycle more efficient for your developers, you would add the following Maven Surefire plugin configuration to your project's POM. Specifying the groups parameter allows you to select one or more, comma-separate group names which will be executed by TestNG.

<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>org.sonatype.mcookbook</groupId>
  <artifactId>testng-groups</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>testng-groups</name>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
      <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-surefire-plugin</artifactId>
       <configuration>
         <groups>unit</groups>
       </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>5.10</version>
      <classifier>jdk15</classifier>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

When you execute mvn test, you will see that the Maven Surefire plugin will only execute four of the five tests in SeriousComponentTest.

7.4.3. Detail

If you wanted to run all tests in the SeriousComponentTest, you could configure your POM to have the following Maven Surefire configuration:

      <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-surefire-plugin</artifactId>
       <configuration>
         <groups>unit, integration</groups>
       </configuration>
      </plugin>

Alternatively, you could just define a dependency on the "unit" group withint the SeriousComponentTest class on the testLargeFile() method. Here's the annotation syntax you would use to do this:

  @Test(groups={"integration"}, dependsOnGroups={"unit"})
  public void testLargeFile() throws Exception {
    String text = "TEST";
    // Imagine that this method contained some serious
    // code that loaded a 100k line text file and
    // tested each line.
    assert SeriousComponent.testSeriousness(text);
  }

Then, in your project's POM, you would simply configure TestNG to run the "integration" group. TestNG would take note of the dependency defined in the test class and execute the "unit" group before the "integration" group.

      <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-surefire-plugin</artifactId>
       <configuration>
         <groups>integration</groups>
       </configuration>
      </plugin>

TestNG supports a very rich set of configuration possibilities for defining groups. You can have groups which depend on other groups, groups can be defined in Test Suite XML files, and you can match groups based on regular expressions to allow for platform specific customizations. Getting into the details of TestNG groups is well beyond the scope of this book, if you would like more information about TestNG, please see the TestNG project documentation here: http://testng.org/doc/documentation-main.html#test-groups.