I need to save all the test data into a properties
file or a JSON
file (since they're easier to read than an XML
). I'm thinking of using a single properties file for storing data for the entire project. Not sure whether that's doable or not.
I am using TestNG
test framework with it's @DataProvider
annotation to tag a function that will return a 2D array. Here's an example of what this can look like:
/*
* This returns 2 parameters for each test execution
*/
@DataProvider(name = "info on cars")
public Object[][] testDataOnCars(){
return new Object[][]{
{"Mercedes as key", "Value with any special char ~!@#$%^&*()_'\",./<>? "}, {"Jaguar", "<>?,./;':\"[]\{}|~!@#$%^&*()_ `"}
}
}
The corresponding test for this could look like:
@Test(dataprovider = "info on cars")
public void testAllCars(String carName, String carDetails){
// Do something with carName and carDetails
}
Some test might require a different number of parameters for a different dataset. For example:
/*
* This returns 4 parameters for each test execution
*/
@DataProvider(name = "info on bank statements")
public Object[][] testDataOnBankStatements(){
return new Object[][]{
{"Credit card payment", "200", "debit", "5th May, 2022"},
{"Salary credit", "5200", "credit", "5th May, 2022"},
}
}
This might be consumed by test function with 4 params:
@Test(dataprovider = "info on bank statements")
public void testAllCars(String description, Integer amount, String debitOrCredit, String date){
// Do something with the 4 params
}
Does anyone know:
- How can I organize test data into a file? Is it better to have a properties file or a JSON file or some other kind of file? It is a 2D array with many parameters tied together.
- Is it advisable to store different test data into the same properties file? Or should I have a separate file for each kind of test data (like 1 file for bank stuff - 5 parameters, another file for travel stuff - 3 parameters etc).
- How do I read this kind of structured data from the file and pass them as a 2D array of
Object[][]
?
CodePudding user response:
Say you have src/test/resources/test_data.json
file which looks like
{
"infoOnCars": [
["Mercedes as key", "Value with any special char ~!@#$%^&*()_'\\\",./<>? "],
["Jaguar", "<>?,./;':\\\"[]\\{}|~!@#$%^&*()_ `"]
],
"infoOnBankStatements": [
["Credit card payment", "200", "debit", "5th May, 2022"],
["Salary credit", "5200", "credit", "5th May, 2022"]
]
}
Then you can add org.json
dependency to your project and implement the following:
public class DataProviderTest {
private JSONObject jsonObject;
private JSONObject getJsonObject() throws URISyntaxException, IOException {
if(jsonObject == null){
jsonObject = new JSONObject(
Files.readString(Paths.get(DataProviderTest.class.getClassLoader().getResource("test_data.json").toURI()))
);
}
return jsonObject;
}
@DataProvider(name = "cars")
Iterator<Object[]> getCars() throws URISyntaxException, IOException {
return getIterator(getJsonObject(), "infoOnCars");
}
@DataProvider(name = "banks")
Iterator<Object[]> getBanks() throws URISyntaxException, IOException {
return getIterator(getJsonObject(), "infoOnBankStatements");
}
Iterator<Object[]> getIterator(JSONObject jsonObject, String key){
Map<String, Object> map = jsonObject.toMap();
Object val = map.get(key);
if(val instanceof ArrayList){
Iterator<ArrayList> valArray = ((ArrayList) val).iterator();
return new Iterator<>() {
@Override
public boolean hasNext() {
return valArray.hasNext();
}
@Override
public Object[] next() {
return valArray.next().toArray();
}
};
}
return null;
}
@Test(dataProvider = "cars")
public void test1(String carName, String carDetails){
System.out.println(">>>> Cars test started");
System.out.println("Car name: " carName);
System.out.println("Car details: " carDetails);
}
@Test(dataProvider = "banks")
public void test2(String description, String amount, String debitOrCredit, String date){
System.out.println(">>>> Bank test started");
System.out.println("Description: " description);
System.out.println("Amount: " amount);
System.out.println("Debit / Credit: " debitOrCredit);
System.out.println("Date: " date);
}
}
It would parse all data as strings. So that you would need to do some conversion to use numbers as numbers.