Data Providers
Here’s a deep dive into TestNG’s @DataProvider feature, covering everything from basic syntax to advanced usages like inheritance and dynamic data based on the test method.
1. What Are DataProviders in TestNG? #
A DataProvider is a factory for test data. It lets you feed the same @Test method with multiple sets of parameters, driving data-driven testing without duplicating test code.
2. DataProvider Syntax #
@DataProvider(name = “myData”)
public Object[][] myDataProviderMethod() {
return new Object[][] {
{ /* first row */ val1, val2, … },
{ /* second row */ val1b, val2b, … },
// …
};
}
- Return type:
- Object[][] (each sub-array is one invocation’s arguments)
- or Iterator<Object[]>
- Name: defaults to the method name; you can override via name = “…”.
- Optional parallelism: @DataProvider(name=”x”, parallel=true) runs rows in parallel threads.
3. How To Use DataProviders in TestNG #
- Define the provider method in the same class (or a separate utility class).
- Annotate your test with dataProvider=”…”.
public class LoginTests {
@DataProvider(name = “credentials”)
public Object[][] creds() {
return new Object[][] {
{ “alice”, “pass1” },
{ “bob”, “pass2” }
};
}
@Test(dataProvider = “credentials”)
public void loginTest(String username, String password) {
// This test runs twice:
// 1) username=”alice”, password=”pass1″
// 2) username=”bob”, password=”pass2″
performLogin(username, password);
Assert.assertTrue(isLoggedIn());
}
}
4. Inherited DataProviders #
If you want to reuse providers across multiple test classes, you can:
A. In a superclass #
public class BaseData {
@DataProvider
public Object[][] numbers() {
return new Object[][] { {1},{2},{3} };
}
}
public class MyTests extends BaseData {
@Test(dataProvider = “numbers”)
public void testNumber(int n) {
System.out.println(“n = ” + n);
}
}
B. In a separate class #
public class Utils {
@DataProvider(name=”users”)
public static Object[][] userProvider() { … }
}
public class UserTests {
@Test(dataProvider=”users”, dataProviderClass=Utils.class)
public void testUser(String username) { … }
}
5. MultiValue DataProviders #
Any provider can supply multiple parameters per invocation by returning sub‐arrays with more elements:
@DataProvider(name = “calculatorData”)
public Object[][] calcData() {
return new Object[][] {
// {a, b, expectedSum, expectedProduct}
{ 2, 3, 5, 6 },
{ 4, 5, 9, 20 }
};
}
@Test(dataProvider = “calculatorData”)
public void mathTest(int a, int b, int sum, int product) {
Assert.assertEquals(a + b, sum);
Assert.assertEquals(a * b, product);
}
6. DataProviders With Method As Parameter #
You can make your provider dynamic by inspecting which test method is calling it:
@DataProvider(name = “dynamic”)
public Object[][] dynamicProvider(Method m) {
if (m.getName().equals(“testA”)) {
return new Object[][] { {“A1”},{“A2”} };
} else if (m.getName().equals(“testB”)) {
return new Object[][] { {“B1”},{“B2”},{“B3”} };
}
return new Object[0][];
}
@Test(dataProvider = “dynamic”)
public void testA(String data) { System.out.println(“A: ” + data); }
@Test(dataProvider = “dynamic”)
public void testB(String data) { System.out.println(“B: ” + data); }
- Signature: provider must accept a java.lang.reflect.Method (and/or ITestContext) before returning the data.
- Allows you to tailor the data set per test.
Summary #
- @DataProvider gives you a clean way to run a test multiple times with different inputs.
- You can inherit providers in superclasses or external classes (dataProviderClass).
- Providers can return multi-column data sets.
- By adding a Method parameter, you can dispatch different data to different tests from the same provider.
Use DataProviders for robust, maintainable, data-driven TestNG suites!