In the last tutorial, we discussed the TestNG Parameters and how to use them for passing the values to your test class from the XML file. But, there is a problem with TestNG parameters. They worked very well to pass the value and run the tests, but that happens only once per execution. What if I want to run the same test with multiple values? Can I do that with parameters? No, I can't since this is a very common operation while testing; there needs to be a standard way to accomplish this goal. It is where TestNG DataProviders come into the picture, and this tutorial will cover just that. Along with the introduction, we will learn the following to use TestNG dataproviders efficiently:

  • What are DataProviders in TestNG?
    • DataProvider syntax
  • How To Use DataProviders In TestNG?
  • Inherited DataProviders in TestNG.
    • MultiValue DataProviders in TestNG.
  • DataProviders With Method As Parameters.

What are DataProviders in TestNG?

The DataProviders in TestNG are another way to pass the parameters in the test function, the other one being TestNG parameters. DataProviders pass different values to the TestNG Test Case in a single execution and in the form of TestNG Annotations. It is a part of the inbuilt TestNG data-driven testing for which TestNG is quite popular. DataProviders help in passing the parameters in different ways. These will be confusing if discussed here. Hence their division into separate sections. The next article will brief you on the syntax of TestNG DataProviders.

DataProvider Syntax:

The TestNG DataProvider is used in the following manner:

@DataProvider (name = "name_of_dataprovider")
public Object[][] dpMethod() {
    return new Object [][] { values}
}

After the introduction of this syntax, there are a few things that you should take note of before writing a test case:

  • The TestNG DataProvider (the annotation part) contains only one single attribute, which is its name. It is always a string type in nature. For example, "name_of_dataprovider", as mentioned above.
  • DataProviders are not declared on top of the functions like TestNG parameters but have a method of their own, which in regular speaking terms called a dataprovider method. For example, dpMethod here.
  • If the tester has not specified the name of the dataprovider, then the method name becomes the dataprovider name by default.
  • TestNG dataprovider returns a 2d list of objects.
  • The method then performs a data-driven test for each value that you have specified.
  • The dataprovider name calls the dataprovider method, and if there is no name specified by the tester, then the dataprovider method is the default name used in the receiving @Test case.

How To Use DataProvider In TestNG?

If you have understood the above-said points, using dataproviders is very easy. We will start with a straightforward and basic DataProvider test first. Observe the following code, which contains the @DataProvider.

import org.testng.annotations.DataProvider;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class DP
{
    @DataProvider (name = "data-provider")
     public Object[][] dpMethod(){
	 return new Object[][] {{"First-Value"}, {"Second-Value"}};
     }
	
    @Test (dataProvider = "data-provider")
    public void myTest (String val) {
        System.out.println("Passed Parameter Is : " + val);
    }
}

Note: You need to import the DataProvider in TestNG by adding the line import org.testng.annotations.DataProvider;

In the above code, I am trying to pass the values "First-Value" and "Second-Value" to the Test method "myTest" with the help of the DataProvider method "*dpMethod()". Please refer to the syntax section to recall the points once again.

Run the code with Run As -> TestNG Test and see the output. dataprovider in testng output

Note: Unlike parameters in TestNG, the dataproviders can be run directly through the test case file.

Both the values appear in the output. It means that even though we ran the file once, the test case method ran twice with different values.

So, even though it is a small and simple code, you might know with how messy codes can get if you have while testing. Wouldn't it be better if we could declare TestNG dataprovider in another class and our test case into another? It is inheriting the dataproviders.

Inherited DataProvider In TestNG

Dataprovider and the test case method can also be in two different classes. It is inheriting the dataprovider since we are inheriting it from another file. It's required to slightly improve the above code to run the test case like this.

The following is the @Test file below :

import org.testng.annotations.Test;

public class DataProvider {
    @Test (dataProvider = "data-provider", dataProviderClass = DP.class)
    public void myTest (String val) {
      System.out.println("Current Status : " + val);
    }
}

The only difference here is that along with the name of dataProvider; you now need to provide the dataProviderClass by the same attribute name.

Since I told this method that my dataprovider class is DP.java, I will create another file DP.java and write my dataprovider code there.

DP.java looks like this:

import org.testng.annotations.DataProvider;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class DP
{
    @DataProvider (name = "data-provider")
     public Object[][] dpMethod(){
        return new Object[][] {{"Value Passed"}};
     } 
}

Run the test file and see if the output is "Value Passed" or not. Inherited DataProvider In TestNG

The output says that the variable value "Value Passed" was actually passed to the method. This is great!! In the above codes, though, if you notice, we have just passed a single parameter per execution of the test case. Practically, we need much more. In the next section, we will see how to pass multiple parameters in the TestNG dataprovider.

How To Pass Multiple Parameters In TestNG DataProviders?

Passing multiple parameters is just similar to the single parameters, but we will be providing multiple values in a single parameter. Observe the following test code, which checks if the sum of two integers is as expected or not.

import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DProvider {
	@DataProvider (name = "data-provider")
	public Object[][] dpMethod(){
		return new Object[][] {{2, 3 , 5}, {5, 7, 9}};
	}
	
      @Test (dataProvider = "data-provider")
      public void myTest (int a, int b, int result) {
	     int sum = a + b;
	     Assert.assertEquals(result, sum);
      }
}

In the above code, I have passed three values a,b and result to check if the sum is equal to result or not.

The output is as follows: multiple_parameters_dp

Can you guess which test failed?

Alright! So, we have passed multiple parameters into the same test method. As an upgrade to this situation, we can pass the same dataprovider to various test methods also. Just provide the same name in every test method, and you are good to go. You can try that as a practice lesson on your own.

DataProviders With Method As A Parameter

In the above cases, we have used one way to provide the dataprovider to another test class, i.e., by creating a dataprovider method for each method that will be calling it. It is alright, but we will unnecessarily increase the lines of code in the java file, which is considered a bad coding practice. If I can do the same job for seven lines instead of 10, I should go for it. It is the reason that dataproviders also accept a method as a parameter, and then we can just check the method name and provide the parameters according to it.

Observe the following code:

import org.testng.Assert;
import java.lang.reflect.Method;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class DProvider {
	@DataProvider (name = "data-provider")
	public Object[][] dpMethod (Method m){
		switch (m.getName()) {
		case "Sum": 
			return new Object[][] {{2, 3 , 5}, {5, 7, 9}};
		case "Diff": 
			return new Object[][] {{2, 3, -1}, {5, 7, -2}};
		}
		return null;
		
	}
	
	@Test (dataProvider = "data-provider")
	 public void Sum (int a, int b, int result) {
	      int sum = a + b;
	      Assert.assertEquals(result, sum);
	 }
	  
	@Test (dataProvider = "data-provider")
	public void Diff (int a, int b, int result) {
	      int diff = a - b;
	      Assert.assertEquals(result, diff);
	 }
}

This code provides a switch case to check the name of the method and return the parameters according to the method name.

Import Required: import java.lang.reflect.Method;

Run the above code and see how the output compares: dataprovider with parameters

A single execution failed where the expectation was the sum of 5 and 7 to be 9, whose failure was bound to happen. You can see how in 5 lines, I created dataprovider for two different test methods. Notice that for every method added to the given dataprovider code, you just need to add two lines:

case "method" :

return statement.

which can also happen in a single line. I am doing this instead of adding the 7 - 8 lines typically. You can compare how efficient this is.

It was all from my side on the topic of dataproviders in TestNG. If you get the codes used in this tutorial, there is no need to tell you how efficient dataproviders are in passing the parameters. On the other hand, it would be wrong to assume that they are a better choice than Parameters in TestNG. Both of these concepts are used differently and depends on the needs of the tester. So, master both of them with different scenarios and different datasets. We will move onto our next topic now.

Common Questions On TestNG DataProviders

How do you give parameters in TestNG?
There are two ways to pass the parameters in TestNG:

  • TestNG Parameters
  • TestNG DataProviders

What is the difference between DataProvider and Parameter in TestNG?
DataProviders pass the different parameters on a single test in a single execution, whereas parameters pass the parameters just once per execution in TestNG.

TestNG Parameters
TestNG Parameters
Previous Article
TestNG Test Case Priority And Sequence
TestNG Test Case Priority And Sequence
Next Article
Harish Rajora
I am a computer science engineer. I love to keep growing as the technological world grows. I feel there is no powerful tool than a computer to change the world in any way. Apart from my field of study, I like reading books a lot and developing new stuff.
Reviewers
Lakshay Sharma's Photo
Lakshay Sharma

Similar Articles

Feedback