Context:
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
The problem here is that you are combining two forms of support that TestNG offers when it comes to a data driven test.
@Parameters
and @DataProvider
are basically two variants of a data driven support approach that TestNG has to offer and so they are essentially mutually exclusive. So you cannot combine both of them together out of the box.
That being said there's an easy way of doing it. You can always access the current <test>
parameters via the ITestContext
. The below modified example shows you how to do this.
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.util.Optional;
public class SampleTestCase {
@Test(priority = 1, dataProvider = "loginCredentials", dataProviderClass = LoginDataProvider.class)
public void handleSuccessLogin(String testDataIdMark, String phoneNumber, String password) {
ITestResult currentTestResult = Reporter.getCurrentTestResult();
//The below approach reads the current <test> or its enclosing <suite> level defined parameters
String rawValue = currentTestResult.getTestContext().getCurrentXmlTest().getParameter("testDataId");
String testDataId = Optional.ofNullable(rawValue).orElse(rawValue);
System.out.println("testDataidMark " + testDataIdMark);
System.out.println("phoneNumber " + phoneNumber);
System.out.println("password " + password);
System.out.println("testDataId " + testDataId);
}
public static class LoginDataProvider {
@DataProvider(name = "loginCredentials")
public Object[][] getTestData() {
return new Object[][]{{"1", "123456", "111111"}, {"2", "654321", "222222"}};
}
}
}