TestNG DataProvider Example
In this article, I am going to show you some examples of DataProvider
.
It is one of the methods used in TestNG to support data-driven testing.
Before I proceed with my examples, I will brief you on data-driven testing but first let’s get started with the setup details:
- I am using Eclipse as the IDE, version Luna 4.4.1.
- I will be running the tests using eclipse TestNG plugin so you need to install TestNG Eclipse Plugin.
1. What is data-driven testing?
There are times when we would like to run our tests against different data sets. Instead of hard coding the data set within tests itself, it will be more appropriate if we could pass our data as parameters to the test method. Thus the test logic remains same but the data on which the test is run changes and this is called data-driven testing.
One of the most important features of TestNG is its data-driven testing. It allows the user to pass parameter values to the test method as arguments, so the test ends up running for each data-set passed in.
TestNG supports two different ways of injecting parameter values.
- Parameterization through
testng.xml
- DataProvider
In order to know when we should use DataProvider
, we also need to know a bit about the other method where we inject parameter values through testng.xml
.
There is also the factory way where we create multiple instances of the test class with different constructor data.
2. Parameter Example
Parameterization through testng.xml
is one of the methods of injecting parameter values. This method is useful if the data set is limited to just a few rows and the values are of simple types like String
, int
etc. The parameters are declared in testng.xml, where
the name
attribute defines name of the parameter and value
attribute defines the parameter value.
paramTestng.xml:
<?xml version="1.0" encoding="UTF-8"?> <suite name="ParameterExampleSuite" parallel="false"> <test name="ParameterTest"> <classes> <parameter name="param1" value="2"></parameter> <parameter name="param2" value="and a string parameter"></parameter> <class name="com.javacodegeeks.testng.ParameterExample"/> </classes> </test> </suite>
You will have to use @Parameters
annotation to pass the parameter values. The parameter name has to be same as the one declared in testng.xml
.
ParameterExample:
package com.javacodegeeks.testng; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class ParameterExample { @Parameters({"param1", "param2"}) @Test public void paramTest(int p1, String p2) { System.out.println("Parameter Example: Data(" + p1 + ", " + p2 + ")"); } }
Output:
[TestNG] Running: C:\javacodegeeks_ws\testNgDataProvider\test\com\javacodegeeks\testng\parmTestng.xml Parameter Example: Data(2, and a string parameter) =============================================== ParameterExampleSuite Total tests run: 1, Failures: 0, Skips: 0 ===============================================
3. Example of DataProvider
If you want to provide the test data, the DataProvider
way, then we need to declare a method that returns the data set in the form of two dimensional object array Object[][]
. The first array represents a data set whereas the second array contains the parameter values.
The DataProvider
method can be in the same test class or one of its super classes. It is also possible to provide DataProvider
in another class but then the method has to be static. I will go into the details in my next example on static DataProvider
.
Once we have added the method we need to annotate it using @DataProvider
to let TestNG know that it is a DataProvider
method. You can also provide a name to it using the name
attribute of the DataProvider
annotation but this is optional. If one hasn’t provided the name, name of the method will be used to refer to it.
If a test wants to use the DataProvider
, it can do so by specifying the name of the DataProvider
in dataProvider
attribute of @Test
annotation.
Define the test class in testng.xml
.
testng.xml:
<?xml version="1.0" encoding="UTF-8"?> <suite name="DataProviderExampleSuite" parallel="false"> <test name="InstanceDataProviderTest"> <classes> <class name="com.javacodegeeks.testng.InstanceDataProviderExample"/> </classes> </test> </suite>
We have provided the DataProvider
method getData
within the test class itself. Note that it is annotated with @DataProvider
. Since it doesn’t have the name
attribute, its name by default will be getData
. It returns two sets of data, each set of which contains two values, an integer and a string value.
We want the test method instanceDbProvider
to run for each set of data that DataProvider
method getData
returns. In order for the test method instanceDbProvider
to use the DataProvider
, we need to specify the DataProvider
name in the dataProvider
attribute of @Test
annotation.
InstanceDataProviderExample:
package com.javacodegeeks.testng; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class InstanceDataProviderExample { @Test(dataProvider="getData") public void instanceDbProvider(int p1, String p2) { System.out.println("Instance DataProvider Example: Data(" + p1 + ", " + p2 + ")"); } @DataProvider public Object[][] getData() { return new Object[][]{{5, "five"}, {6, "six"}}; } }
Output:
[TestNG] Running: C:\javacodegeeks_ws\testNgDataProvider\test\com\javacodegeeks\testng\testng.xml Instance DataProvider Example: Data(5, five) Instance DataProvider Example: Data(6, six) =============================================== DataProviderExampleSuite Total tests run: 2, Failures: 0, Skips: 0 ===============================================
4. Example of static DataProvider
DataProvider
method can also be defined in a separate class as a static method, in which case, the test method using it has to specify both the DataProvider
name and its class in the @Test
attributes dataProvider
and dataProviderClass
.
staticDataProviderTestng.xml:
<?xml version="1.0" encoding="UTF-8"?> <suite name="StaticDataProviderExampleSuite" parallel="false"> <test name="StaticDataProviderTest"> <classes> <class name="com.javacodegeeks.testng.StaticDataProviderExample"/> </classes> </test> </suite>
StaticDataProviderExample:
package com.javacodegeeks.testng; import org.testng.annotations.Test; public class StaticDataProviderExample { @Test(dataProvider="client1", dataProviderClass=DataProviderSource.class) public void client1Test(Integer p) { System.out.println("Client1 testing: Data(" + p + ")"); } @Test(dataProvider="client2", dataProviderClass=DataProviderSource.class) public void client2Test(Integer p) { System.out.println("Client2 testing: Data(" + p + ")"); } }
Output:
[TestNG] Running: C:\javacodegeeks_ws\testNgDataProvider\test\com\javacodegeeks\testng\staticDataProviderTestng.xml Client1 testing: Data(1) Client2 testing: Data(2) =============================================== StaticDataProviderExampleSuite Total tests run: 2, Failures: 0, Skips: 0 ===============================================
5. Example of DataProviders with Method and ITestContext parameters
Till now we have seen DataProvider
methods without any parameters. Now I am going to show you other variations of DataProvider
methods which can receive two types of parameters Method
and ITestContext
. This is useful if you want to use the same DataProvider
but want different data sets returned, based on the test method being invoked or the test suite/test type it belongs to.
You can specify just the Method
parameter or ITestContext
parameter or both the parameters. Based on the parameters used, TestNg will set the parameter values before invoking the DataProvider
method.
In this example, I have three types of tests:
- UnitLevel
- AcceptanceLevel
- IntegrationLevel
In case of UnitLevel
testing, the DataProvider
returns different data sets based on the test method being invoked.
In case of AcceptanceLevel
and IntegrationLevel
testing, the DataProvider
returns different data sets based on the test type.
We define the test types and their classes in paramDataProviderTestng.xml
.
paramDataProviderTestng.xml:
<?xml version="1.0" encoding="UTF-8"?> <suite name="DataProviderParameterExampleSuite" parallel="false"> <test name="UnitLevel"> <classes> <class name="com.javacodegeeks.testng.DataProviderParametersExample"/> </classes> </test> <test name="AcceptanceLevel"> <classes> <class name="com.javacodegeeks.testng.DataProviderParametersAcceptanceExample"/> </classes> </test> <test name="IntegrationLevel"> <classes> <class name="com.javacodegeeks.testng.DataProviderParametersIntegrationExample"/> </classes> </test> </suite>
Class DataProviderParametersExample
contains test methods for UnitLevel
testing. For each test method, the DataProvider
should be able to provide different data sets.
DataProviderParametersExample:
package com.javacodegeeks.testng; import org.testng.annotations.Test; public class DataProviderParametersExample { @Test(dataProvider="scenarioData", dataProviderClass=DataProviderSource.class) public void scenario1(String scenarioData) { System.out.println("Scenario testing: Data(" + scenarioData + ")"); } @Test(dataProvider="scenarioData", dataProviderClass=DataProviderSource.class) public void scenario2(String scenarioData) { System.out.println("Scenario testing: Data(" + scenarioData + ")"); } @Test(dataProvider="scenarioData", dataProviderClass=DataProviderSource.class) public void commonScenarios(String scenarioData) { System.out.println("Common Scenarios testing: Data(" + scenarioData + ")"); } }
Class DataProviderParametersAcceptanceExample
has just one test method for AcceptanceLevel
testing.
DataProviderParametersAcceptanceExample:
package com.javacodegeeks.testng; import org.testng.annotations.Test; public class DataProviderParametersAcceptanceExample { @Test(dataProvider="TestType", dataProviderClass=DataProviderSource.class) public void acceptanceTest(String data) { System.out.println("Acceptance testing: Data(" + data + ")"); } }
Class DataProviderParametersIntegrationExample
contains method for IntegrationLevel
testing. If you notice, it uses the same dataProvider
as the one used by AcceptanceLevel
test.
DataProviderParametersIntegrationExample:
package com.javacodegeeks.testng; import org.testng.annotations.Test; public class DataProviderParametersIntegrationExample { @Test(dataProvider="TestType", dataProviderClass=DataProviderSource.class) public void integrationTest(String data) { System.out.println("Integration testing: Data(" + data + ")"); } }
The DataProviderSource
contains all the DataProvider
methods required for UnitLevel
, AcceptanceLevel
and IntegrationLevel
. Method getScenarioData
returns different data sets for each UnitLevel
test methods. Likewise, method getTestTypeData
returns different data sets based on the test type AcceptanceLevel
or IntegrationLevel
.
DataProviderSource:
package com.javacodegeeks.testng; import java.lang.reflect.Method; import org.testng.ITestContext; import org.testng.annotations.DataProvider; public class DataProviderSource { @DataProvider(name="client1") public static Object[][] getClient1Data() { return new Object[][]{{1}}; } @DataProvider(name="client2") public static Object[][] getClient2Data() { return new Object[][]{{2}}; } @DataProvider(name="scenarioData") public static Object[][] getScenarioData(Method method) { String testCase = method.getName(); if ("scenario1".equals(testCase)) { return new Object[][]{{"Scenario1 data"}}; } else if ("scenario2".equals(testCase)) { return new Object[][]{{"Scenario2 data"}}; } else { return new Object[][]{{"Common scenario data"}}; } } @DataProvider(name="TestType") public static Object[][] getTestTypeData(ITestContext context) { String testName = context.getName(); if ("IntegrationLevel".equals(testName)) { return new Object[][]{{"Integration test data"}}; } else if ("AcceptanceLevel".equals(testName)) { return new Object[][]{{"Acceptance test data"}}; } else { return new Object[][]{{"Common test data"}}; } } }
Output:
[TestNG] Running: C:\javacodegeeks_ws\testNgDataProvider\test\com\javacodegeeks\testng\paramDataProviderTestng.xml Common Scenarios testing: Data(Common scenario data) Scenario testing: Data(Scenario1 data) Scenario testing: Data(Scenario2 data) Acceptance testing: Data(Acceptance test data) Integration testing: Data(Integration test data) =============================================== DataProviderParameterExampleSuite Total tests run: 5, Failures: 0, Skips: 0 ===============================================
6. Example of DataProvider returning strong typed Objects
In this example, DataProvider
returns a strong typed java object like Employee
objects instead of primitive types like String
.
Define the test class in empTestng.xml
.
empTestng.xml:
<?xml version="1.0" encoding="UTF-8"?> <suite name="DataProviderParameterEmpSuite" parallel="false"> <test name="EmpTest"> <classes> <class name="com.javacodegeeks.testng.DataProviderParametersEmployeeExample"/> </classes> </test> </suite>
The Employee
bean that our DataProvider
will return.
Employee:
package com.javacodegeeks.testng; public class Employee { private String name; public Employee(String name) { this.name = name; } public String toString() { return "Employee: " + name; } }
In the below test class, DataProvider
method getEmployeeData
returns an array of Employee
objects.
DataProviderParametersEmployeeExample:
package com.javacodegeeks.testng; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderParametersEmployeeExample { @Test(dataProvider="employeeData") public void empTest(Employee employee) { System.out.println("Employee testing: Data(" + employee + ")"); } @DataProvider(name="employeeData") public Object[][] getEmployeeData() { return new Object[][]{{new Employee("Joe")}, {new Employee("Sam")}}; } }
Output:
[TestNG] Running: C:\javacodegeeks_ws\testNgDataProvider\test\com\javacodegeeks\testng\empTestng.xml Employee testing: Data(Employee: Joe) Employee testing: Data(Employee: Sam) =============================================== DataProviderParameterEmpSuite Total tests run: 2, Failures: 0, Skips: 0 ===============================================
Download the Eclipse Project
In this article I have shown you several examples of TestNG DataProvider.
You can download the full source code of this example here: testNgDataProvider.zip