 ------
 Using TestNG
 ------
 Brett Porter <brett@apache.org>
 ------
 2010-01-09
 ------
 
 ~~ Licensed to the Apache Software Foundation (ASF) under one
 ~~ or more contributor license agreements.  See the NOTICE file
 ~~ distributed with this work for additional information
 ~~ regarding copyright ownership.  The ASF licenses this file
 ~~ to you under the Apache License, Version 2.0 (the
 ~~ "License"); you may not use this file except in compliance
 ~~ with the License.  You may obtain a copy of the License at
 ~~
 ~~   http://www.apache.org/licenses/LICENSE-2.0
 ~~
 ~~ Unless required by applicable law or agreed to in writing,
 ~~ software distributed under the License is distributed on an
 ~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 ~~ KIND, either express or implied.  See the License for the
 ~~ specific language governing permissions and limitations
 ~~ under the License.

 ~~ NOTE: For help with the syntax of this file, see:
 ~~ http://maven.apache.org/doxia/references/apt-format.html

Using TestNG

* Unsupported TestNG versions

  - TestNG 5.14.3: Bad formatted pom.xml.
  - TestNG 5.14.4 and 5.14.5: TestNG is using a missing dependency (org.testng:guice:2.0). Excluding it, may break some features.

* Configuring TestNG

  To get started with TestNG, include the following dependency in your project (replacing the version with the one you wish to use):

+---+
<dependencies>
  [...]
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>6.9.8</version>
      <scope>test</scope>
    </dependency>
  [...]
</dependencies>
+---+

  If you are using an older version of TestNG (\<= 5.11), the dependency would instead look like this:

+---+
<dependencies>
  [...]
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>5.11</version>
      <scope>test</scope>
      <classifier>jdk15</classifier>
    </dependency>
  [...]
</dependencies>
+---+

  <<Note:>> if you are using JDK 1.4 Javadoc annotations for your TestNG tests, replace the classifier <<<jdk15>>> with <<<jdk14>>> above.

#{if}(${project.artifactId}=="maven-surefire-plugin")
  This is the only step that is required to get started - you can now create tests in your test source directory
  (e.g., <<<src/test/java>>>). As long as they are named in accordance with the defaults such as <<<*Test.java>>> they will be run
  by ${thisPlugin} as TestNG tests.
#{else}
  This is the only step that is required to get started - you can now create tests in your test source directory
  (e,g., <<<src/test/java>>>). As long as they are named in accordance with the defaults such as <<<*IT.java>>> they will be run
  by ${thisPlugin} as TestNG tests.
#{end}

  If you'd like to use a different naming scheme, you can change the <<<includes>>> parameter, as discussed in the
  {{{./inclusion-exclusion.html}Inclusions and Exclusions of Tests}} example.

* Using Suite XML Files

  Another alternative is to use TestNG suite XML files. This allows flexible configuration of the tests to be run.
  These files are created in the normal way, and then added to the ${thisPlugin} Plugin configuration:

+---+
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          <suiteXmlFiles>
            <suiteXmlFile>testng.xml</suiteXmlFile>
          </suiteXmlFiles>
        </configuration>
      </plugin>
    [...]
</plugins>
+---+

  This configuration will override the includes and excludes patterns and run all tests in the suite files.

* Specifying Test Parameters

  Your TestNG test can accept parameters with the <<<@Parameters>>> annotation.  You can also pass parameters from Maven
  into your TestNG test, by specifying them as system properties, like this:

+---+
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          <systemPropertyVariables>
            <propertyName>firefox</propertyName>
          </systemPropertyVariables>
        </configuration>
      </plugin>
    [...]
</plugins>
+---+

  For more information about setting system properties in ${thisPlugin} tests, see {{{./system-properties.html}System Properties}}.

* Using Groups

  TestNG allows you to group your tests. You can then execute one or more specific groups. To do this with ${thisPlugin},
  use the <<<groups>>> parameter, for example:

+---+
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          <groups>functest,perftest</groups>
        </configuration>
      </plugin>
    [...]
</plugins>
+---+

  Likewise, the <<<excludedGroups>>> parameter can be used to run all but a certain set of groups.

* Running Tests in Parallel

  TestNG allows you to run your tests in parallel, including JUnit tests. To do this, you must set the
  <<<parallel>>> parameter, and may change the <<<threadCount>>> parameter if the default of 5 is not sufficient.
  For example:

+---+
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          <parallel>methods</parallel>
          <threadCount>10</threadCount>
        </configuration>
      </plugin>
    [...]
</plugins>
+---+

  This is particularly useful for slow tests that can have high concurrency, or to quickly and roughly assess the independence
  and thread safety of your tests and code.
  
  TestNG 5.10 and plugin version 2.19 or higher allows you to run methods in parallel test using data provider.
  
+---+
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          <properties>
            <property>
              <name>parallel</name>
              <value>methods</value>
            </property>
            <property>
              <name>dataproviderthreadcount</name>
              <value>30</value>
            </property>
          </properties>
        </configuration>
      </plugin>
    [...]
</plugins>
+---+
  
  TestNG 6.9.8 (JRE 1.7) and plugin version 2.19 or higher allows you to run suites in parallel.
  
+---+
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          <suiteXmlFiles>
            <file>src/test/resources/testng1.xml</file>
            <file>src/test/resources/testng2.xml</file>
          </suiteXmlFiles>
          <properties>
            <property>
              <name>suitethreadpoolsize</name>
              <value>2</value>
            </property>
          </properties>
        </configuration>
      </plugin>
    [...]
</plugins>
+---+

  See also {{{./fork-options-and-parallel-execution.html}Fork Options and Parallel Test Execution}}.

* Using Custom Listeners and Reporters

  TestNG provides support for attaching custom listeners, reporters, annotation transformers and method interceptors to your tests.
  By default, TestNG attaches a few basic listeners to generate HTML and XML reports.

  Unsupported versions:
    - TestNG 5.14.1 and 5.14.2: Due to an internal TestNG issue, listeners and reporters are not working with TestNG.
           Please upgrade TestNG to version 5.14.9 or higher.
           Note: It may be fixed in a future surefire version.

  You can configure multiple custom listeners like this:

+---+
<dependencies>
[...]
  <dependency>
    <groupId>your-testng-listener-artifact-groupid</groupId>
    <artifactId>your-testng-listener-artifact-artifactid</artifactId>
    <version>your-testng-listener-artifact-version</version>
    <scope>test</scope>
  </dependency>
[...]
</dependencies>
[...]
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          <properties>
            <property>
              <name>usedefaultlisteners</name>
              <value>false</value> <!-- disabling default listeners is optional -->
            </property>
            <property>
              <name>listener</name>
              <value>com.mycompany.MyResultListener,com.mycompany.MyAnnotationTransformer,com.mycompany.MyMethodInterceptor</value>
            </property>
            <property>
              <name>reporter</name>
              <value>listenReport.Reporter</value>
            </property>
          </properties>
        </configuration>
      </plugin>
    [...]
</plugins>
+---+

  For more information on TestNG, see the {{{http://www.testng.org}TestNG web site}}.

  You can implement TestNG listener interface <<<org.testng.ITestListener>>> in
  a separate test artifact <<<your-testng-listener-artifact>>> with scope=test, or in project test source code
  <<<src/test/java>>>. You can filter test artifacts by the parameter <<<dependenciesToScan>>> to load its classes
  in current ClassLoader of surefire-testng provider. The TestNG reporter class should implement <<<org.testng.IReporter>>>.

* The level of verbosity

  Since the plugin version 2.19 or higher the verbosity level can be configured in provider property
  <<<surefire.testng.verbose>>>. The verbosity level is between 0 and 10 where 10 is the most detailed.
  You can specify -1 and this will put TestNG in debug mode (no longer slicing off stack traces and all).
  The default level is 0.
  
+---+
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          [...]
          <properties>
            <property>
              <name>surefire.testng.verbose</name>
              <value>10</value>
            </property>
          </properties>
          [...]
        </configuration>
      </plugin>
    [...]
</plugins>
+---+

* Customizing TestNG Object Factory

  Since the plugin version 2.19 and TestNG 5.7 or higher you can customize
  TestNG object factory by implementing <<<org.testng.IObjectFactory>>> and
  binding the class name to the key <<<objectfactory>>> in provider properties:
  
+---+
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          [...]
          <properties>
            <property>
              <name>objectfactory</name>
              <value>testng.objectfactory.TestNGCustomObjectFactory</value>
            </property>
          </properties>
          [...]
        </configuration>
      </plugin>
    [...]
</plugins>
+---+

* Customizing TestNG Test Runner Factory

  Since the plugin version 2.19 and TestNG 5.9 or higher you can customize
  TestNG runner factory by implementing <<<org.testng.ITestRunnerFactory>>> and
  binding the class name to the key <<<testrunfactory>>> in provider properties:
  
+---+
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          [...]
          <properties>
            <property>
              <name>testrunfactory</name>
              <value>testng.testrunnerfactory.TestNGCustomTestRunnerFactory</value>
            </property>
          </properties>
          [...]
        </configuration>
      </plugin>
    [...]
</plugins>
+---+

* Running 'testnames' in test tag

  Only tests defined in a <<<test>>> tag matching one of these names will be run.
  In this example two tests run out of 7; namely <InstallTest> and <ATest>.
  The test <a-t3> does not match any test in <suite.xml>.
  
+---+
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          [...]
          <suiteXmlFiles>
            <file>src/test/resources/suite.xml</file>
          </suiteXmlFiles>
          <properties>
            <property>
              <name>testnames</name>
              <value>a-t1,a-t3</value>
            </property>
          </properties>
          [...]
        </configuration>
      </plugin>
    [...]
</plugins>
+---+


  The test suite 'suite.xml' :

+---+
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Component Tests" verbose="2" annotations="JDK">
  <test name="a-t1" preserve-order="true" >
    <classes>
      <class name="server.InstallTest" />
      <class name="server.ATest" />
    </classes>
  </test>
  <test name="a-t2" preserve-order="true" >
    <classes>
      <class name="server.SCHTest" />
      <class name="server.PRGTest" />
      <class name="server.SIBBTest" />
      <class name="server.EDNTest" />
      <class name="server.PPVTest" />
    </classes>
  </test>
</suite>
+---+


* Running TestNG and JUnit Tests

  TestNG 6.5.1 and higher provides support to run TestNG and JUnit 4.x in current Maven project. All you need
  is to introduce TestNG and JUnit dependency in POM.

+---+
<dependencies>
  [...]
  <dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>6.9.4</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
  </dependency>
  [...]
</dependencies>
+---+

  You may want to run two providers, e.g. <<<surefire-junit47>>> and <<<surefire-testng>>>, and avoid running JUnit
  tests within <<<surefire-testng>>> provider by setting property <<<junit=false>>> (note that this property is not applicable if you configure the <<<suiteXmlFiles>>> parameter).

+---+
<plugins>
    [...]
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          [...]
          <properties>
            <property>
              <name>junit</name>
              <value>false</value>
            </property>
          </properties>
          <threadCount>1</threadCount>
          [...]
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.apache.maven.surefire</groupId>
            <artifactId>surefire-junit47</artifactId>
            <version>${project.version}</version>
          </dependency>
          <dependency>
            <groupId>org.apache.maven.surefire</groupId>
            <artifactId>surefire-testng</artifactId>
            <version>${project.version}</version>
          </dependency>
        </dependencies>
      </plugin>
    [...]
</plugins>
+---+


