How to use a single dataProvider for a sequence of testcases?

74 Views Asked by At

My use case is that I have a base testcase that consumes a data provider, and a single instance of that data provider is used by a sequence of test cases.

@Test(dataProvider="TestData", dataProviderClass = ExcelDataProvider.class)
public void baseTest(String data[]){
 data1 = data[0];
 data2 = data[1];
 data3 = data[2];

 //The below testcases are sequence testcases, each testcase is implemented in seperate class file and the test method is annotated with @Test

 TC01Impl tc1 = new TC01Impl(driver);
 tc1.TestCase1(data1);

 TC02Impl tc2 = new TC02Impl(driver);
 tc2.TestCase2(data2);

 TC03Impl tc3 = new TC03Impl(driver);
 tc3.TestCase3(data3);
}

I am using Listeners for taking screenshot and attaching to the report incase if there is testcase failure. It is working good and also attaching the correct screenshot, but the problem is it's showing baseTest as fail. I want the particular testcase in which the failure occurs to be in the report. How can we do that.

2

There are 2 best solutions below

0
sashkins On

It looks like you are running 3 different tests in a single @Test method (TestCase1, TestCase2, TestCase3). So if TestCase1 fails, TestCase2 and TestCase3 won't be executed at all, and your baseTest method will be marked as failed. That's the expected behavior because TestCase1, TestCase2, and TestCase3 mean nothing to the TestNG, they are just parts of the actual test 'baseTest' (annotated with @Test).

In order to have 3 tests executed, and consequently have 3 tests in the report, you need to create 3 separate methods annotated with the @Test annotation, and pass the same data provider to all of them (I'd recommend reviewing the data provider itself, as each of your tests seems to require a single string as a parameter, so you don't have to move an array around)



public class YourTestSuite {

    @Test(dataProviderClass = ExcelDataProvider.class, dataProvider = "TestData")
    public void testCase1(String[] data) {
        TC01Impl tc1 = new TC01Impl(driver);
        tc1.testCase1(data[0]);
    }

    @Test(dataProviderClass = ExcelDataProvider.class, dataProvider = "TestData")
    public void testCase2(String[] data) {
        TC02Impl tc2 = new TC02Impl(driver);
        tc2.testCase2(data[1]);
    }

    @Test(dataProviderClass = ExcelDataProvider.class, dataProvider = "TestData")
    public void testCase3(String[] data) {
        TC03Impl tc3 = new TC03Impl(driver);
        tc3.testCase3(data[2]);
    }
}

It would probably make sense to mark testCase1, testCase2, and testCase3 methods with the @Test annotation, and run all test methods from the TC01Impl, TC02Impl, and TC03Impl classes, instead of having an extra class for doing the same.

5
Krishnan Mahadevan On

You should perhaps work with a Factory powered data driven test.

Below is a sample that shows how to work with this.

import org.testng.annotations.DataProvider;
import org.testng.annotations.Factory;
import org.testng.annotations.Test;

public class FactoryTestCase {

    private final Object[] data;

    @Factory(dataProvider = "dp")
    public FactoryTestCase(Object[] data) {
        this.data = data;
    }

    @Test
    public void t1() {
        System.err.println("First string parameter : " + data[0]);

    }

    @Test
    public void t2() {
        System.err.println("Second boolean parameter : " + data[1]);
    }

    @Test
    public void t3() {
        System.err.println("Third integer parameter : " + data[2]);

    }

    @DataProvider(name = "dp")
    public static Object[] getData() {
        return new Object[]{
                new Object[]{"a", false, 1},
                new Object[]{"b", true, 2},
                new Object[]{"c", false, 3}
        };
    }
}