White Box Testing
Test your code
   Home      UnitTestingWithTestNG
 

TestNG is a testing framework inspired from JUnit and NUnit but introducing some new functionalties that make it more powerful and easier to use, such as:

  • Annotations.

  • Run your tests in arbitrarily big thread pools with various policies available (all methods in their own thread, one thread per test class, etc...).

  • Test that your code is multithread safe.

  • Flexible test configuration.

  • Support for data-driven testing (with @DataProvider).

  • Support for parameters.

  • Powerful execution model (no more TestSuite).

  • Supported by a variety of tools and plug-ins (Eclipse, IDEA, Maven, etc...).

  • Embeds BeanShell for further flexibility.

  • Default JDK functions for runtime and logging (no dependencies).

  • Dependent methods for application server testing.

 

Test method(Test cases)

Write test method for each method of every class file to be tested. Method name must begin with annotation @Test. Annotation @Test identifies that this method is a test method. Following are the test annotation to write test method.

@Test Annotation identifies that this method is a test method.

@Test

public final void testAdd1() {

   Calculator cal = new Calculator();

   long result = cal.add(3, 4);

   Assert.assertEquals(result, 7, "actual not matching with expected");

}

@Test(expectedExceptions = ArithmeticException.class) if the method throws the named exception and fails if the different exception thrown or test method does not throw an exception.

@Test(expectedExceptions = ArithmeticException.class)

public void exceptionTest() {

   Calculator cal = new Calculator();

   cal.divide(1, 0);

}

@Test(timeOut=100) Fails if the method takes longer than specified timeout 100 milliseconds.

@Test(timeOut=100)

public final void testAdd2() {

   Calculator cal = new Calculator();

   long result = cal.add(3, 4);

   Assert.assertEquals(result, 7, "actual not matching with expected");

}

@Test(enabled=false) if code changed and test are not ready to run this time.

@Test(enabled=false)

public final void testRational() {

   Calculator cal = new Calculator();

   long result = cal.rational(10, 4);

   Assert.assertEquals(result, 2, "actual not matching with expected");

}

@Test(invocationCount = 10) will invoke test 10 times. This method is typically useful for stress testing to test the SUT for number of request serially

@Test(invocationCount = 10)

public final void testAdd3() {

   Calculator cal = new Calculator();

   long result = cal.add(3, 4);

   Assert.assertEquals(result, 7, "actual not matching with expected");

}

@Test(threadPoolSize = 5, invocationCount = 10) to invoke test 10 times with 5 threads in thread pool. As soon as test complete thread return to thread pool to invoke remaining tests. This annotation useful to verify that SUT is multithread safe.

@Test(threadPoolSize = 5, invocationCount = 10)

public void concurrencyTest() {

   System.out.print(" " + Thread.currentThread().getId());

}


Test method setup and teardown

All the unit tests of a test class share the fixture code. In order to run each test independently, fixture setup starting with annotation @BeforeMethod will be called before each one of the test method get executed, and the fixture teardown starting with annotation @AfterMethod will be called after each test method get executed.

@BeforeMethod

public void setUpBeforeMethod()

{

}

 

@AfterMethod

public void tearDownAfterMethod()

{

}


Test groups

Test groups further allow to classify test methods in various groups. In any software development lifecycle we have different sets of test cases some of them overlapping with each other for example unit test, build acceptance test, functional test etc. A test method can be part of multiple groups. With the help of test groups we can test particular group of test method without recompiling the binaries again and again

@Test(groups = {"unit-test","functional-test"})

public final void testAdd4() {

   Calculator cal = new Calculator();

   long result = cal.add(3, 4);

   Assert.assertEquals(result, 7, "actual not matching with expected");

}


Test groups setup and teardown

In order to share fixture code for groups, use annotation  @BeforeGroups and @AfterGroups.

The list of groups configured for fixture method will run this fixture method. Fixture setup starting with annotation @BeforeGroups will be called before the first test method of the groups configured for this fixture, and the fixture teardown starting with annotation @AfterGroups will be called after all the test method of the groups configured for this fixture. Test groups setup and teardown will be called one time before/after all the test method of the groups configured.

@BeforeGroups(groups = {"unit-test","functional-test"})

public void setUpBeforeFTandRT()

{

}

@AfterGroups(groups = {"unit-test","functional-test"})

public void tearDownAfterFTandRT()

{

}


Test classes

Write test classes for every class to be tested.

 

A typical test class comprises of following components

Test class fixture setup starting with annotation @BeforeClass.

Test method fixture setup starting with annotation @BeforeMethod.

Unit tests starting with annotation @Test

Test method fixture teardown starting with annotation @AfterMethod.

Test class fixture teardown starting with annotation @AfterClass.

 

Test class setup and teardown

In order to share fixture code class wide, use annotation @BeforeClass and @AfterClass. Fixture setup starting with annotation @BeforeClass will be called before all the test method of the class get executed , and the fixture teardown starting with annotation @AfterClass will be called after all the test method of the class get executed. Test class setup and teardown will be called one time before and after all the test cases.

@BeforeClass

public void setUpBeforeClass()

{

}

@AfterClass

public void tearDownAfterClass()

{

}


Running the Test Classes

You can run test classes in following several ways

  • With testng.xml file and command line

  • Programmatically generating testing.xml


With testng.xml file and command line

Create testng.xml

<!DOCTYPEsuite SYSTEM"http://testng.org/testng-1.0.dtd">

 

<suite name="SuiteMain" verbose="1">

<test name="UnitTest">

    <classes>

        <class name="CalculatorTestAdd"/>

    <class name="CalculatorTestSubtract"/>

    </classes>

  </test>

</suite>


run the test suite with following command

java -classpath testng.jar org.testng.TestNG testng.xml -testclass SampleTest

 

Programmatically generating testing.xml

//Create test suite

XmlSuite suite = new XmlSuite();

suite.setName("SuiteMain");

suite.setVerbose(1);

//Create test

XmlTest test = new XmlTest(suite);

test.setName("UnitTest");

//Create classes and add the test classes

List<XmlClass> classes = new ArrayList<XmlClass>();

classes.add(new XmlClass("CalculatorTestAdd"));

classes.add(new XmlClass("CalculatorTestSubtract"));

//set test classes

test.setXmlClasses(classes) ;

//Create suites from number of test suite

List<XmlSuite> suites = new ArrayList<XmlSuite>();

suites.add(suite);

// Pass XmlSuite to TestNG

TestNG tng = new TestNG();

tng.setXmlSuites(suites);

tng.run();

 

Dependency Testing

Dependencies allows test method ordering and dependency on each other.

Test method dependency could be on method or groups using dependsOnMethods or dependsOnGroups attribute of @annotation. If at least one of the dependency method get failed dependent method will be skipped and reported as SKIP in reports

Test method ordering can be done using “alwaysRun=true” along with dependsOnMethods or dependsOnGroups attribute of @annotation. If any of the dependency method get failed dependent method will not be skipped. This is also known as soft dependency

@Test(groups = {"setup"})

public void setUpEnvironment() {}

@Test(dependsOnMethods = {"setUpEnvironment"})

public void method1() {}

@Test(groups = { "setup" })

public void resourceInit() {}

@Test(dependsOnMethods = { "setup*" })

public void method2() {}

 

Test parameters from Testng.xml

Test parameters from testng.xml allows simple test parameter values for your test method

import org.testng.annotations.*;


public class SampleTest{

   @Test

   @Parameters(value="name")

   public void nameTest(String name) {

      System.out.println("Name is " + name);

   }

}

 

Testing.xml

 

<!DOCTYPEsuite SYSTEM"http://beust.com/testng/testng-1.0.dtd">

 

<suite name="TestSuite">

  <test name="NameTest"> 

  <parameter name="Name"value="Robert"/>

    <classes>

      <class name="SampleTest"/>

    </classes>

  </test>

</suite>

 

 
Sample Source Code
 
 

 
External References