paul
paul

Reputation: 4487

Run entire test class with first row of dataprovider

Setup:

  1. I have a test class.
  2. This test class has several methods with @Test(dataProvider = "getData") annotation.
  3. There are 7 records (rows) in data.
  4. All tests are sequential.

Problem:

I need to run all methods (tests) with one row of data, but as of now it keeps on repeating same tests on all rows i.e. if there is 7 rows of data then test 1 will run 7 times and then second test will start and same happen for second test and so on.

I want all tests to run for row 1 and then all tests run again for row2.

I am using Apache poi APIs to read data from ms-excel sheet. Java, testng and Selenium to automate the browser on Windows.

I have visited following link but didn't get the implementation: https://dzone.com/articles/testng-run-tests-sequentially

Upvotes: 1

Views: 2899

Answers (2)

Grasshopper
Grasshopper

Reputation: 9058

Factory allows one to create tests dynamically.

Assume this is the current setup...

SequentialTest.java - Sample portion

@Test(dataProvider="dp")
public void firstTest(int id, String account) {
    System.out.println("Test #1 with data: "+id+". "+account);
}

Data.java - Sample portion

@DataProvider(name="dp")
public static Object[][] dataProvider() {
    Object[][] dataArray = { {1, "user1"}, {2, "user2"} };
    return dataArray;
}

Maybe you have the dataprovider in same class.

testng.xml - Relevant portion

< test name = "checks">
   < classes >
      < class name="....Sequential" />
   < /classes >
< /test>

As per the article the changes that are required in the classes and xml.

SequentialTest.java - Create instance variables for each parameter that were earlier passed to the test method. Create a constructor with the instance variables. Remove the dataprovider part from Test annotation. Remove the parameters from the test methods.

private int id;
private String account;

public SequentialTest(int id, String account) {
    this.id = id;
    this.account = account;
}

@Test
public void firstTest() {
    System.out.println("Test #1 with data: "+id+". "+account);
    assertTrue(true);
}

Data.java - Need to separate the dataprovider method into a separate class (if not already) and add the factory method to it. Dataprovider remains the same.

@Factory(dataProvider="dp")
    public Object[] createInstances(int id, String account) {
        return new Object[] {new SequentialTest(id, account)};
}

testng.xml - Remove the existing portion. Need to mention only the name of the class containing the Factory method. Most important add the group-by-instances="true" parameter which will get you the desired behaviour.

  < test name="fact" group-by-instances="true">
      < classes>
          < class name="....Data"/>
      < classes/>
  < /test>

Upvotes: 2

Aditya Gaurav
Aditya Gaurav

Reputation: 78

While writing your dataprovider, you can add an attribute 'indices' to the dataprovider. For ex

//Define the index you want to return it to. Here it will return first row
@DataProvider(name = "dataProviderSample", indices = {0})
public Object[][] getSelectedData() {
    return getInputData();
}

// Write your logic to generate data form excel/csv/json/xml inside the below method
private static Object[][] getInputData() {
    return new Object[][]{{"Sample1", "Sample1", "Sample1"},
            {"Sample2", "Sample2", "Sample2"},
            {"Sample3", "Sample3", "Sample3"},
            {"Sample4", "Sample5", "Sample5"}
    };
}

Through the above approach, you can pass the expected index in your test method.

@Test(dataProvider = "dataProviderSample")
void testDataProvider(String fname, String lName, String num) {
    System.out.println(fname);
    System.out.println(lName);
    System.out.println(num);
}

So by using this approach, you can pass one row at a time in your all test methods. But If you want to pass all rows of dataprovider in your test methods.

Upvotes: 1

Related Questions