Home > Software design >  How can I structure multiple 2D arrays of test data into a properties file and read them for my test
How can I structure multiple 2D arrays of test data into a properties file and read them for my test

Time:05-13

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:

  1. 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.
  2. 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).
  3. 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.

  • Related