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 !!