2

I have used test dat provider and factory with sample data more like reading from excel rows with multiple values. So each Map denotes Column name and value of each row and adding it to list have all the values which are read from excel. Now am returning Object[][] of List<HashMap>, so in factory it has to be in same signature. Here if I put each list to map, then only only instance I can execute. Is there a way to have HashMap returned for each list index so that Test method executes based on the size of arraylist.

public class TestNG {
ArrayList<HashMap<String, String>> natives;
@DataProvider(name = "create")
public static Object[][] createData() {
    System.out.println("In data provider");
    ArrayList<HashMap<String, String>> check = new ArrayList<HashMap<String, String>>();
    HashMap<String, String> hash_map = new HashMap<String, String>();
    hash_map.put("2", "Two");
    hash_map.put("3", "Three");
    check.add(hash_map);
    HashMap<String, String> hash_map1 = new HashMap<String, String>();
    hash_map1.put("21", "Two1");
    hash_map1.put("31", "Three1");
    check.add(hash_map1);
    return new Object[][] { { check } };
}

@Test
public void test() {
    System.out.println("ID is " + Thread.currentThread().getId());
    System.out.println(natives);
}

@Factory(dataProvider = "create", dataProviderClass = TestNG.class)
public Object[] checking1(ArrayList<HashMap<String, String>> map) {
    System.out.println("In Factory");
    natives = map;
    return new Object[] { natives };

}

}

I see when I use return new Object[]{new HashMap<String,String> values, new HashMap<String,String> value}, test method will be invoked twice. So is there a way to achieve this with above approach?

I have looked into all possible solutions which are available but couldn't find anything concrete to approach.

Here is the output I get.

[RemoteTestNG] detected TestNG version 6.14.3
In data provider
In Factory
ID is 1
[{2=Two, 3=Three}, {31=Three1, 21=Two1}]

So, test method is called only once , since we are passing List on a whole which is understandable . But want it to execute number of times equal to list length. Any better way to approach?

Gautham M
  • 4,816
  • 3
  • 15
  • 37
Sriram S
  • 169
  • 14

1 Answers1

1

Actually it looks like the Factory method is not required in this case. Since the whole list is passed as a single test case, the test is only executed once. You need to convert the list into an Object[][] where each test case would be a Map:

Either you could pass it as:

return new Object[][]{ {hash_map}, {hash_map1}};

OR if there are lot of maps in the list or if the list is populated from a different source, then you could do the following stream operation (if you are using java 8 or above). (If you are using a version below java 8, then you could use a for loop to do the same)

At the end of the data provider:

return check.stream()
            .map(m -> new Object[] { m } )
            .toArray(Object[][]::new);

Instead of using a factory you could modify the test as:

@Test(dataProvider = "create")
public void test(HashMap<String, String> map) {
    System.out.println("ID is " + Thread.currentThread().getId());
    System.out.println(map);
}
Gautham M
  • 4,816
  • 3
  • 15
  • 37
  • Yeah above one would work . But the reason I had factory is because suppose if there are other annotations like BeforeClass, BeforeMethod , etc , then I would need to run each of those methods too each time for the test data. So I would need factory in that case. Thats why having that in the script . – Sriram S May 19 '21 at 13:45
  • @SriramS anyway by converting the data as above in data provider, it would work with factory as well. – Gautham M May 19 '21 at 13:47
  • Thats absolutely true . But imagine in case where I have beforeclass and afterclass methods along with test method. Scenario 01- With only data provider,(assume two list of maps returned ), it will invoke before class once, after class once and test method twice(since we have 2 data). Scenario 02- with factory getting value from data provider makes before class,aftercalss and test methods all to run twice. So scenario 02 is what I am looking for to achieve. Thats why having factory in place – Sriram S May 20 '21 at 02:34
  • @SriramS for Scenario 2, if using `Factory` is "only" for running before/after class for each test case, then I would suggest the use of `BeforeMethod` and `AfterMethod`. – Gautham M May 20 '21 at 04:39