Search code examples
unit-testingtestngparameterized-unit-test

Nested tests in TestNG


In TestNG I have a parameterized Test A which automatically creates n tests from a dataProvider, and a Test B which should be executed each time a test in A finishes as I want to take advantage of the result obtained in A. In other words, I would like to know is it's possible to have the following:

Given a parameterized @Test A(dataProvider = "inputList") and a @Test B, TestNG would create the following unit tests and execute them in the following order:

Test A1
Test B1 (Based on A1 result)
Test A2
Test B2 (Based on B2 result)
...

Test An
Test Bn (Based on An result)

Is it possible with any existing TestNG tag? I know I could treat @Test B as an @After but this wouldn't be understood for TestNG as a test and I need Test B to be seen as a test for later reports.


Solution

  • You can use a TestNG Factory. e.g.:

    On a Factory Method

    public class TestClass {
        private final int p1;
        private final int p2;
    
        public TestClass(int p1, int p2) {
            this.p1 = p1;
            this.p2 = p2;
        }
    
        @Factory(dataProvider = "inputList")
        public static Object[] createTestClasses() {
            return new Object[]{
                    new TestClass(1, 1),
                    new TestClass(1, 0),
                    new TestClass(1, -1),
            };
        }
    
        @Test
        public void A() {
            // test `A` code, stores result in some class member field
        }
    
        @Test(dependsOnMethods = {"A"})
        public void B() {
            // test `B` code, uses stored result from test `A`
        }
    }
    

    On a Constructor

    public class TestClass {
        private final int p1;
        private final int p2;
    
        @Factory(dataProvider = "inputList")
        public TestClass(int p1, int p2) {
            this.p1 = p1;
            this.p2 = p2;
        }
    
        @DataProvider
        public static Object[][] inputList() {
            return new Object[][]{
                    {1, 1},
                    {1, 0},
                    {1, -1}
            };
        }
    
        @Test
        public void A() {
            // test `A` code, stores result in some class member field
        }
    
        @Test(dependsOnMethods = {"A"})
        public void B() {
            // test `B` code, uses stored result from test `A`
        }
    }
    

    See Factories in the TestNG documentation page.