Is there a way to send arguments to DataProviders

1,193 views
Skip to first unread message

VanderRock s

unread,
Mar 9, 2022, 1:52:57 PM3/9/22
to testng-users
Is there a way to send arguments to DataProviders? I want to create a single DataProvider which will access the excel workbook name from a HashMap depending on the argument value (used as key in the Map). I know one way would be to assign a new property to the ITestContext, but  from my google searches, I found many people trying to do something similar so just wanted to find out if this feature has been introduced in the newer testNG releases. Thank you

VanderRock s

unread,
Mar 9, 2022, 2:04:54 PM3/9/22
to testng-users
Sorry I actually I take back a portion of what I said. There is no way to send the ITestcontext from within the testCase using a dataprovider method to set the workbook name. So suppose the same class has two dataProvider tests that use the same DataProvider method but need to access two different workbooks then how can i pass this information to the dataprovider?

⇜Krishnan Mahadevan⇝

unread,
Mar 10, 2022, 1:58:41 AM3/10/22
to testng-users
Its not clear as to what you are asking for.
The data provider by itself is meant to be providing data. Are you saying you would like to pass in some sort of a parameter which the data provider can use to determine which data source to pick test data from? For e.g., which sheet to read from in a given excel sheet?

If that's the case, who exactly is going to be passing this value? 

You can natively inject either a ITestContext object (which corresponds to the <test> tag) or a Method object (which corresponds to which test method is this data provider being executed for).

Please refer to the Native dependency section in the documentation: https://testng.org/doc/documentation-main.html#native-dependency-injection

So if you inject an ITestContext object, then you can essentially read the values of the <parameters> that you have set at the <test> level in your suite xml file, using the ITestContext object.

Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribblings @ https://rationaleemotions.com/


--
You received this message because you are subscribed to the Google Groups "testng-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to testng-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/testng-users/dda451fe-881a-48c0-841d-0516dd04bb94n%40googlegroups.com.
Message has been deleted

VanderRock s

unread,
Mar 10, 2022, 11:44:41 PM3/10/22
to testng-users
So my intent is as below, or something similar. Basically reuse same dataprovider used for different tests in same test script or in different test scripts. you were right, just provide the workbook name as a parameter from the @Test so dataprovider knows which workbook to pick data from. If that is not possible, how can the below be achieved using ITestContext, since it is not possible to pass an Itestcontext from withing the @Test?:

Dataprovider will be in a separate class (say abc.java)
@DataProvider (name = "name_of_dataprovider") 
   public Object[][] dpMethod(String workbookName) { 
        return new Object [][] { values} 
   }

From Test Script 1
@Test (dataProvider = " dpMethod",  dataproviderclass="abc", workbookName="workbook1.xlsx"
public void myTest1 (String val) { 
      System.out.println("Passed Parameter Is : " + val); 
}

@Test (dataProvider = " dpMethod",  dataproviderclass="abc", workbookName="workbook2.xlsx"
public void myTest2 (String val) { 
      System.out.println("Passed Parameter Is : " + val); 
}

from Test Script 2
@Test (dataProvider = " dpMethod",  dataproviderclass="abc", workbookName="workbook3.xlsx"
public void myTest3 (String val) { 
      System.out.println("Passed Parameter Is : " + val); 
}

⇜Krishnan Mahadevan⇝

unread,
Mar 11, 2022, 1:30:25 AM3/11/22
to testng-users
Shruti,


Test method invokes the data provider. This is incorrect. Depending on whether the data provider is lazy or eager, TestNG keeps toggling between the data provider and the test method. So the test method never invokes the data provider. TestNG invokes the data provider and keeps all the data in memory (if its eager data provider) or it gets one set of test data at time (if its a lazy data provider) and then invokes the test method with the test data obtained from the data provider.

So if you were to make use of the ITestContext, then you would just add it as a parameter to your data provider method. TestNG will take care of passing an instance of ITestContext to this.

You could define parameters from your suite xml file which will basically be read by the data provider by querying the ITestContext object.

The other alternative is that you create a custom annotation that represents the excel sheet name from the workbook and then parse the annotation via the injected Method object in your data provider and then do work accordingly.

Here's a quick sample that shows how to do this:

Java
import static java.lang.annotation.ElementType.METHOD;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({METHOD})
public @interface ExcelDataSourceInfo {

  String sheetName();

  String filepath();
}
Java
import java.lang.reflect.Method;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class GenericDataProviderTest {

  @ExcelDataSourceInfo(sheetName = "sheet1", filepath = "src/test/resources/foo.xls")
  @Test(dataProvider = "dp")
  public void test1(String data) {
    System.err.println("String received " + data);
  }

  @ExcelDataSourceInfo(sheetName = "sheet2", filepath = "src/test/resources/foo.xls")
  @Test(dataProvider = "dp")
  public void test2(int data) {
    System.err.println("Integer received " + data);
  }

  @DataProvider(name = "dp")
  public Object[][] genericDataProvider(Method method) {
    ExcelDataSourceInfo info = method.getAnnotation(ExcelDataSourceInfo.class);
    switch (info.sheetName().trim().toLowerCase()) {
      case "sheet1":
      return new Object[][] {
          {"TestNG"},
          {"JUnit5"},
          {"JUnit4"}
      };
      case "sheet2" :
        return new Object[][] {
            {1},
            {2},
            {3}
        };
      default:
        return new Object[][]{{}};
    }
  }
}


Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribblings @ https://rationaleemotions.com/

On Fri, Mar 11, 2022 at 10:13 AM Shruti <shrutikh...@gmail.com> wrote:
So my intent is as below, or something similar. Basically reuse same dataprovider used for different tests in same test script or in different test scripts. you were right, just provide the workbook name as a parameter from the @Test so dataprovider knows which workbook to pick data from. If that is not possible, how can the below be achieved using ITestContext, since it is not possible to pass an Itestcontext from withing the @Test?:

Dataprovider will be in a separate class (say abc.java)
@DataProvider (name = "name_of_dataprovider") 
   public Object[][] dpMethod(String workbookName) { 
        return new Object [][] { values} 
   }

From Test Script 1
@Test (dataProvider = " dpMethod",  dataproviderclass="abc", workbookName="workbook1.xlsx"
public void myTest1 (String val) { 
      System.out.println("Passed Parameter Is : " + val); 
}

@Test (dataProvider = " dpMethod",  dataproviderclass="abc", workbookName="workbook2.xlsx"
public void myTest2 (String val) { 
      System.out.println("Passed Parameter Is : " + val); 
}

from Test Script 2
@Test (dataProvider = " dpMethod",  dataproviderclass="abc", workbookName="workbook3.xlsx"
public void myTest3 (String val) { 
      System.out.println("Passed Parameter Is : " + val); 
}
On Wednesday, March 9, 2022 at 10:58:41 PM UTC-8 Krishnan Mahadevan wrote:

Eric Angeli

unread,
Mar 11, 2022, 9:58:41 AM3/11/22
to testng-users
I had a similar but slightly different need and took a slightly different approach from what Krishnan suggest.
My approach was to add a "data loader" layer on top of data providers. It defines a framework/interface for defining classes that know how to load data and return in a similar format. Then I can reuse the data loaders by just providing the configuration need for the data loader(s). 

I really do like that idea and will probably add support for specifying the configuration information at the test method/class level

Here are some examples of the approach I have so far:  https://github.com/gtque/GoaTE/tree/dev/modules/testng/src/test/java/com/thegoate/testng

It doesn't support what you are looking for, but we are going into the weekend and I don't have anything to do this weekend.

Eric
https://github.com/gtque/GoaTE/tree/dev

VanderRock s

unread,
Mar 15, 2022, 7:02:51 PM3/15/22
to testng-users
Thank you Krishnan, the code you provided helped me achieve what I was looking to do with Data Providers. Thank you!
Reply all
Reply to author
Forward
0 new messages