TestNG @DataProvider for Repeated Tests

An important feature provided by TestNG is the @DataProvider annotation that helps us to write repeated tests or data-driven tests. This essentially means that the same test method can be run multiple times with different data sets.

Please note that @DataProvider is the second way of passing parameters to test methods except passing parameters from testng.xml. @DataProvider helps in passing the complex parameters to the test methods as it is not possible to do with @Parameters.

See Also: TestNG @Parameters Annotation

1. @DataProvider Annotation

To use the @DataProvider feature in the tests, we have to declare a method annotated by @DataProvider and then use this method in the tests using the ‘dataProvider‘ attribute in the @Test annotation.

The name of the data provider ( ‘data-provider’ in this case ) must be used by the test method if it wants to use the datasets provided by the provider method.

public class TestDataProvider {

  @DataProvider(name = "data-provider")
  public Object[][] dataProviderMethod() {
    return new Object[][]{{"data one"}, {"data two"}};
  }

  @Test(dataProvider = "data-provider")
  public void testMethod(String data) {
    System.out.println("Data is: " + data);
  }
}

The execution of the test method is dependent upon the number of data sets defined by the @DataProvider annotated method. In the above example, testMethod() will be executed twice. The first time the values of parameter data will be ‘data one’ and the second time it will be ‘data two’.

Data is: data one
Data is: data two

PASSED: testMethod("data one")
PASSED: testMethod("data two")

===============================================
Default Suite
Total tests run: 2, Passes: 2, Failures: 0, Skips: 0
===============================================

Data providers can run in parallel with the attribute parallel:

@DataProvider(parallel = true)

2. Eager vs Lazy Parameters

The Data Provider method can return one of the following types:

2.1. Eager Initialization with Object[][]

The first dimension’s size is the number of times the test method will be invoked and the second dimension size contains an array of objects that must be compatible with the parameter types of the test method. Using this method we eagerly initialize the parameters.

@DataProvider(name = "create")
public static Object[][] createData() {
  return new Object[][]{
      new Object[]{1, "one"},
      new Object[]{2, "two"},
      new Object[]{3, "three"},
      new Object[]{4, "four"}
  };
}

@Test(dataProvider = "create")
public void test(Integer num, String display) {
  System.out.println("num is: " + num + " and display is: " + display);
} 

2.2. Lazy Initialization with Iterator<Object[]>

Lazy alternative of Object[][]. Causes the test method to be invoked once for each element of the iterator. TestNG will invoke the iterator and then the test method with the parameters returned by this iterator one by one.

@DataProvider(name = "createWithIterator")
public Iterator<Object[]> createDataWithIterator() {
  return Arrays.asList(
      new Object[]{1, "one"},
      new Object[]{2, "two"},
      new Object[]{3, "three"},
      new Object[]{4, "four"}
  ).iterator();
}

@Test(dataProvider = "create")
public void test(Integer num, String display) {
  System.out.println("num is: " + num + " and display is: " + display);
} 

3. Using @DataProvider and @Test in Separate Classes

If we have declared a separate class as the data provider, we need to create an static method in that class with the same syntax as in the previous example.

Next, we must use the dataProviderClass attribute of the @Test annotation.

To understand this, add two classes with the names DataProviderClass and TestClass as below.

3.1. DataProviderClass.java

Note that If we want to put the data provider in a different class, it needs to be a static method or a class with a non-arg constructor.

import org.testng.annotations.DataProvider;

public class DataProviderClass
{
	@DataProvider(name = "data-provider")
	public static Object[][] dataProviderMethod()
	{
		return new Object[][] { { "data one" }, { "data two" } };
	}
}

3.2. TestClass.java

import org.testng.annotations.Test;

public class TestClass
{
	@Test(dataProvider = "data-provider", dataProviderClass = DataProviderClass.class)
	public void testMethod(String data)
	{
		System.out.println("Data is: " + data);
	}
}

3.3. Demo

Now run the above test.

Data is: data one
Data is: data two

PASSED: testMethod("data one")
PASSED: testMethod("data two")

As we can see from the above test results the test method was executed two times depending upon the data passed to it by DataProvider method.

In this scenario, the DataProvider method was in a different class. In such a case the dataProviderMethod() has to be declared static so that it can be used by a test method in a different class for providing data.

Happy Learning !!

Sourcecode on Github

Leave a Reply

8 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.