• November 21, 2024
TestNG

Since it’s creation, the JUnit inspired framework is constantly used across multiple projects and organizations. TestNG is a part of many automation testing strategies where different approaches and patterns are used. The open-source framework is not an extension of JUnit, since it is designed to be better than JUnit by eliminating limitations and adding the already existing features from JUnit plus much more features that allow more flexibility when writing a structured test automation framework.

To list some of the important ones:

  • Annotation support
  • Multi-threaded execution
  • Easy reporting
  • Test Parallelization
  • Test Parameterization
  • Dependency methods and groups

These are some of the features TestNG has, and in this blog, we will focus on two important features used when we have a large set of data and tests to be covered. TestNG Parameterization and Parallelization are some of the main features that many organizations incorporate in their testing strategy.

We’ll take a look at what they are used for and when it is the perfect time to used them.

TestNG Parameterization

TestNG Parameterization
TestNG Parameterization

To put it in simple terms, TestNG Parameterization is the process of running a test over and over again with different input values. This can be useful when a large number of test combinations are needed to be done for one scenario. By doing this we reduce the number of tests we need to create and we just focus on the different set of input values for one test. The test itself would run N times, depending on how many inputs we have. So if we have three combinations of inputs, the test would run three times for each and every set of values.

TestNG Parameterization can be achieved in two ways:

  • @Parameters annotation + TestNG XML file
  • @DataProvider annotation

Let’s explain both in detail.

@Parameters + TestNG XML file

This is one way of having parameterized tests using TestNG. Basically, it consists of one test class and one XML file which contains the set of input values. @Parameters annotation is a method where we set values to be passed as arguments using an XML file.

Let’s create on test class.

public class TestOneClass {

@Test
@Parameters("ParameterizedTest")
public void testOne(String value) {
   System.out.println("The passed parameterized value is:" + value);
   }
}

A simple test which prints a value that we are passing as an argument. Notice the @Parameters(“ParameterizedTest”)?

This is the annotation feature and the name of the XML file we are going to create now.

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >  

<suite name = "Test parameterization File">
   <test name = "Test One">
       <parameter name = "value" value="testNG123"/> 
       <classes>
          <class name = "TestOneClass" />
       </classes>
   </test>
</suite>

In this XML file we specify the suite and test names. We specify the parameter which needs to be the same in the XML and the test class and provide a test value for it. Last but not least, we write the class name which in our case is TestOneClass.

When you run the XML file, TestNG will search the parameter in the test classes and will executed the test once it’s found.

The output from the current test example is: “The passed parameterized value is: testNG123”

@DataProvider

The second and most effective way of TestNG Parameterization is by incorporating @DataProvider into the test framework.

DataProvider is a method where we can pass complex parameters such as objects, data from DB or a property file, etc. As an argument, the DataProvider method takes only the name of the test. The output is an array of objects.

Let’s create a test class.

public class TestTwoClass {

@Test
@Parameters("ParameterizedTest2")
public void testOne(String name, String value) {
   System.out.println("The name of the employee is:" + name + " and the access passcode is: " + value);
   }
}

The DataProvider method would look like this:

@DataProvider(name = "DataProvider1")
public static Object[][] dataFromDataProvider() {
return new Object[][] 
  {
       {"Adam", "123456"}, 
       {"Jack", "test867"}, 
       {"Monica", "code321"}
  };
}

Both, the test and the data provider method can be within the same class or in a separate one. There are three set of input values provided from the DataProvider itself. When we run the test we would get:

"The name of the employee is: Adam and the access passcode is: 123456"
"The name of the employee is: Jack and the access passcode is: test867"
"The name of the employee is: Monica and the access passcode is: code321"

We can pass as many values as we want, especially when we have a complex business logic with large number of set inputs to be covered.

TestNG Parallelization

TestNG Parallelization

As the name says, TestNG Parallelization is the process of running multiple tests in parallel or multithreaded mode. based on the configuration made, different threads are started and the tests within those threads are executed.

The main advantage of using parallelization in your test framework is the reduced execution time of your test suite, especially when you have a large number of tests covering complex business logic.

TestNG parallelization can be achieved on test cases, classes, or suites. We will focus on executing multiple test cases within a class and multiple test classes.

Executing multiple test cases

Let’s take a look at the example below on how you can achieve parallelization for multiple test cases within one test class.

public class ParallelTests
{
  @Test
  public void testOne() {
     long id = Thread.currentThread().getId();
     System.out.println("Test One. Thread id: " + id);
    }

  @Test
  public void testTwo() {
    long id = Thread.currentThread().getId();
    System.out.println("Test Two. Thread id: " + id);
   }

  @Test
  public void testThree() {
    long id = Thread.currentThread().getId();
    System.out.println("Test Three. Thread id: " + id);
   }
}

The class has two test methods which print their names and the thread id. The thread id is the thread in which the test is executed.

Now let’s create the XML file.

<suite name="ParallelTestCases" parallel="methods" thread-count="2" >
  <test name="ParallelTestCases" group-by-instances="true">
    <classes>
      <class name="ParallelTests" />
    </classes>
  </test>
</suite>

When we run the XML file we would get:

"Test Two. Thread ID is 3"
"Test One. Thread ID is 1" 
"Test Three. Thread ID is 6"

Executing multiple test classes

Executing test classes in parallel has the same concept with some small modifications. We write two test classes with two test methods inside those classes.

public class ParallelTestsClass1
{
  @Test
  public void testOne() {
     long id = Thread.currentThread().getId();
     System.out.println("Test One. Thread id: " + id);
    }

  @Test
  public void testTwo() {
    long id = Thread.currentThread().getId();
    System.out.println("Test Two. Thread id: " + id);
   }
}
public class ParallelTestsClass2
{
  @Test
  public void testThree() {
     long id = Thread.currentThread().getId();
     System.out.println("Test Three. Thread id: " + id);
    }

  @Test
  public void testFour() {
    long id = Thread.currentThread().getId();
    System.out.println("Test Four. Thread id: " + id);
   }
}

The XML file would look like this:

<suite name="ParallelTestCases" parallel="classes" thread-count="2" >
  <test name="ParallelTestCases">
    <classes>
      <class name="ParallelTestsClass1" />
      <class name="ParallelTestsClass2" />
    </classes>
  </test>
</suite>

When executing the XML file we get the following output:

"Test Two. Thread ID is 7"
"Test One. Thread ID is 2" 
"Test Three. Thread ID is 9"
"Test Four. Thread ID is 4"

The Bottom Line

By now, you have a clear picture of how powerful TestNG can be. It’s features clearly enhances the level of productivity when automating test cases comes into place. TestNG Parameterization and parallelization are one of the most important features which makes TestNG so globally used across multiple teams. Happy automating!

Share This Post


Latest Post

Vladimir Simonovski
Vladimir Simonovski

Software Automation Engineer with almost 5 years of experience. Involved in many QA activities for the insurance and banking platforms. Follow QAMIND on Twitter and LinkedIn to get fresh content around Software Testing