简体   繁体   中英

is it possible to pass dynamic number of parameters to same testng test with same dataprovider?

I have a testng test method and a data provider for it. I want to make the test case reusable for multiple clients that have this feature to be tested. The only catch is that the feature works differently on different clients that is I have to provide different number of inputs to the same feature for different clients and the end result is same for all.

Currently I am doing this by defining multiple test methods with data providers for multiple clients that have this feature.

Example:-

@DataProvider(name="dp1")
public Object[][] getDataForClient1()
{
   //return data
}

@Test(dataProvider="dp1", groups={"client1"})
public void transferCredit(String senderId,String receiverId,String amount,String expectedResult)
{
   //Perform operation
}

@DataProvider(name="dp2")
public Object[][] getDataForClient2()
{
   //return data
}

@Test(dataProvider="dp2", groups={"client2"})
public void transferCredit(String senderId,String receiverId,String amount,String paymentReference,String expectedResult)
{
   //Perform operation
}

I have developed a common test logic to handle different sets of parameters. What I am not able to do is the reuse the same test method for different sets of parameters.

I want to do it like the following

@DataProvider(name="dp")
public Object[][] getData()
{
   //return data
}

@Test(dataProvider="dp", groups={"client1,client2"})
public void transferCredit(String ... params)
{
   //Perform operation
}

But doing this gives testng exception that is the parameters are not matching. So is there any way to do this in TestNG?

You can wrap the data as an object. As I see it some of the params remain same while some change. So create a class with senderid, receiverid, params and all which are a superset - set only the data you need - based on the method calling the dataprovider and send the array of these objects.

One of the other option (apart from the ones that has already been shared here) is to do something like this

public class TestSample {

    @Test(dataProvider = "dp")
    public void testMethod(Object object) {
        if (object instanceof String[]) {
            System.err.println("Incoming array was " + Arrays.toString((String[]) object));
        }
        if (object instanceof String) {
            System.err.println("Incoming string " + object);
        }

    }

    @DataProvider(name = "dp")
    public Object[][] getData() {
        return new Object[][]{
                {new String[]{"TestNG", "JUnit"}},
                {"Cedric Beust"}
        };
    }
}

But to be honest, I dont think this is a feature request that would be entertained in TestNG. Just my personal opinion.

Not aware of a very clean/straight forward feature to make this accessible though, yet few suggestions would be -

  1. Use the data superset in the DataProvider and while you consume them in different methods, you can ignore the extra parameter in the one which doesn't require all the parameters. Sample -

     @DataProvider(name="dp") public Object[][] getData() { //return data } @Test(dataProvider="dp1", groups={"client1"}) public void transferCredit(String senderId,String receiverId,String amount,String expectedResult) { //Perform operation; Ignore paymentReference } @Test(dataProvider="dp", groups={"client2"}) public void transferCredit(String senderId,String receiverId,String amount,String paymentReference,String expectedResult) { //Perform operation }
  2. You can make use of Method to get to the name of the calling method in the DataProvider and modulate your return object accordingly. Here is the documentation and sample around the same.

    If you declare your @DataProvider as taking a java.lang.reflect.Method as first parameter, TestNG will pass the current test method for this first parameter. This is particularly useful when several test methods use the same @DataProvider and you want it to return different values depending on which test method it is supplying data for.

     @DataProvider(name="dp") public Object[][] getDataForClient2(Method m) { if(m.getName().equals("transferCreditM1") { //do X } else { //do Y } }

Read the existing testng.xml file, modify it during runtime and execute it

What the below code does: I want to add a list of parameters to each during runtime. These parameters are passed as maven runtime arguments. They are read using System.getProperty() method as shown below. Then these parameters are added to the inside and testng is ran successfully. This can be extended based on your requirement.

The below code reads the testng.xml file and adds parameter to

List<String> parameters = new ArrayList<>();
parameters = Arrays.asList(System.getProperty("parameters").split(",");

TestNG tng = new TestNG();
File initialFile = new File("testng.xml");
InputStream inputStream = FileUtils.openInputStream(initialFile);
Parser p = new Parser(inputStream);
List<XmlSuite> suites = p.parseToList();
for(XmlSuite suite:suites){
    List<XmlTest> tests = suite.getTests();
    for (XmlTest test : tests) {
         for (int i = 0; i < parameters.size(); i++) {
            HashMap<String, String> parametersMap = new HashMap<>();
            parametersMap.put("parameter",parameters.get(i));
            test.setParameters(parametersMap);
        }
    }
}
tng.setXmlSuites(suites);
tng.run();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM