Search code examples
javaseleniumtestingtestngtestng-dataprovider

Run every test for a single instance of @DataProvider using a @Factory


I have a test class with about 5+ tests in it that I want to run once for each url sequentially. For example:

URL 1 From @DataProvider:
Test 1: Pass
Test 2: Fail
Test 3: Fail
Test 4: Pass
URL 2 From @DataProvider:
Test 1: Pass
Test 2: Fail
Test 3: Fail
Test 4: Pass

Instead of how it is currently:

URL 1:
Test 1: Pass
URL 2:
Test 1: Pass
URL 1:
Test 2: Fail
URL 2:
Test 2: Fail etc.

I'm pulling the URLs from an excel sheet in my DataProvider like so:

@DataProvider
public Object[][] urlDataProvider() throws Exception {
    File file = new File("ExampleClients.xlsx");
    FileInputStream inputStream = new FileInputStream(file);
    XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
    XSSFSheet sheet = workbook.getSheet("URL's");

    int rowCount = sheet.getLastRowNum();
    Object[][] urlData = new Object[rowCount+1][1];

    for (int i = 0; i <= rowCount; i++) {
        XSSFRow row = sheet.getRow(i);
        XSSFCell cell = row.getCell(0);
        String URL = cell.getStringCellValue();
        urlData[i][0] = URL;
    }
    return urlData;
}

I've tried using a @Factory but am new to the whole QA/TestNG and am confused by it:

@Factory(dataProvider="urlDataProvider")
public CareFirstTests(String url) {
    this.url = url;
}

All of my test methods, @Factory and @DataProvider are in the same java test file. When I try using the Factory I get this error

Couldn't find a constructor in class

I'm also open to hearing any other ways how to accomplish something like this.


Solution

  • If there are no restrictions to convert your tests into individual methods, the above ask can be achieved using below approach. Let me know if this helps.

    import org.testng.Assert;
    import org.testng.annotations.DataProvider;
    import org.testng.annotations.Test;
    
    public class StackTest {
        
        @DataProvider
        public Object[][] returnData(){
            return new Object [][]{{"Input 1"}, {"Input 2"}};
        }
        
        @Test(dataProvider="returnData")
        public void iterativeTest(String val) {
            System.out.println("This is from returned Data : "+ val);
            dp1(val);
            dp2(val);
        }
        
        public void dp1(String val) {
            System.out.println("Value from dp1 : "+ val);
        }
        
        public void dp2(String val) {
            System.out.println("Value from dp2 : "+ val);
            Assert.assertEquals(true, true);
        }
    }