[TestNg] [DataProvider] Parallel Device using Data Provider and @Parameter

Context:

  • My code (Login test case) already passed and it run in parallel device
  • The user credentials are from @DataProvider (the passed test one is using the same credential)

What i want:

  • Use the different credential for each device

I’ve tried to combine the @Parameter and Data Provider like:

@Test(priority = 1, dataProvider = "loginCredentials", dataProviderClass = LoginDataProvider.class)
@Parameters("testDataId")
    public void handleSuccessLogin(String testDataIdMark, String phoneNumber, String password, String testDataId){
        System.out.println("testDataidMark "+testDataIdMark);
        System.out.println("phoneNumber "+ phoneNumber);
        System.out.println("passoword "+ password);
        System.out.println("testDataId "+ testDataId);
}

The DataProvider:

public class LoginDataProvider {
    @DataProvider(name = "loginCredentials")
     public Object[][] getTestData() {
        return new Object[][]{
                {"1", "123456", "111111"},
                {"2", "654321", "222222"}
        };
    }
}

The XML:

<test name="Login">
        <parameter name="appiumPort" value="4723"/>
        <parameter name="platformName" value="android"/>
        <parameter name="platformVersion" value="5"/>
        <parameter name="udid" value="xxxxxx"/>
        <parameter name="appPackage" value="mtda.xxx"/>
        <parameter name="appActivity" value="com.xxx"/>
        <parameter name="testDataId" value="1"/>
        <classes>
            <class name="testcases.LoginTestCase">
            </class>
        </classes>
    </test>

    <test name="Login2">
        <parameter name="appiumPort" value="4725"/>
        <parameter name="platformName" value="android"/>
        <parameter name="platformVersion" value="7"/>
        <parameter name="udid" value="xxxxxx"/>
        <parameter name="appPackage" value="mtda.xxx"/>
        <parameter name="appActivity" value="com.xxx"/>
        <parameter name="testDataId" value="2"/>
        <classes>
            <class name="testcases.LoginTestCase">
            </class>
        </classes>
    </test>

But it return error:

has no parameters defined but was found to be using a data provider (either explicitly specified or inherited from class level annotation).
Data provider mismatch

Yes, you have Data provider mismatch. Data provider is providing this data:

To this method:

So Data Provider is supplying 3 parameters to a method that takes 4 parameters. Do you see the mismatch?

Here is a tutorial on TestNg Data Providers that may help:

1 Like

Hi @wreed , thanks for your time

But my thing is:

I want to use the Data Provider with @Parameter

My goal is “mapping” the data based on the Parameter from my XML

My parameter is testDataId, and i want to get the credential from my Data Provider, like:

if(testDataId.equals(testDataIdFromDataProvider)){
  phoneNumber = phoneNumberFromDataProvider;
  password = passwordFromDataProvider
}

Btw, sorry for my broken English

Yes, i provide 4 params because i want to handle the value from the Data Provider (3 values) with @Parameter(1 value)

CMIIW @wreed

Ok, I understand now, thanks for explaining. I’m looking into this for my own curiosity but I have not gotten to the bottom of it. I need to make sure you understand:

This is not an Appium issue. You are looking at the way to use TestNg annotations. If you want a quicker answer, or possibly a better one, I would suggest you to cross post on the TestNg user group:
https://groups.google.com/g/testng-users

Those people have forgotten more about TestNg than I have ever known.

1 Like

Thanks @wreed , ahh that’s a funny one.

My last question is, since you got my point, do you have other alternative to cover my case?

Ok, I’ve looked into this pretty thoroughly and I think this boils down to something from the link I shared above:

*DataProviders pass the different parameters on a single test in a single execution, whereas parameters pass the parameters just once per execution in TestNG.

So I don’t believe you can use a @Parameter annotation to pass multiple values.

However, once again looking at the link I provided above, you can see that you can parametrize the Data Provider in such a way to achieve what you want.

Take a look at the section titled: DataProviders With Method As A Parameter. You will see that they parametrize based on a method name, like this:

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;
		
	}

It seems to me that there is no reason that you couldn’t leverage this on the device uuid, or the device name, or some other capability, using the getCapability method from driver to address this:

As I said above, you really should cross post to the TestNg users group and see what they think. There may be a better solution that I don’t know about.

1 Like

Hi Wreed, yes, i already asked it on testng Groups. I didn’t even try it first, just to thank a good person like you.

And i will update the thread ASAP.
Here’s the link to my question:

https://groups.google.com/g/testng-users/c/Dmrd4b9trzY

Just for the update, i have read the solution and i think i can achieve my goal by using ITestResult with ITestContext.

I like the solution using Data Provider with “method name”, but in my personal opinion, i think ITestResult with ITestContext is more reliable.

1 Like

I’m just suggesting alternatives. And I definitely know that there are people out there who know a lot more than I do about this subject.

I’m glad you found a good solution.

1 Like