Search code examples
testngdataproviderchain

Use DataProvider in test scenario


If I have multiple @Test methods which must be in a chain and I want to use DataProvider to pass more data for the whole test scenario what is the proper way of doing that.

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

public class TestClass {

   private int type = -1;

   @DataProvider
   public Object[][] mock() {
      return new Object[][] { { 1, "Hello" }, { 2, "World" } };
   }

   @Test(groups = { "A" }, priority = 0, dataProvider = "mock")
   public void testOne(int i, String name) {
      System.out.println("TestClass.testOne()");
      switch (i) {
      case 1:
         type = 1;
         Assert.assertEquals(name, "Hello");
         break;
      case 2:
         type = 2;
         Assert.assertEquals(name, "World");
         break;
      default:
         break;
      }
   }

   @Test(groups = { "A" }, priority = 1)
   public void testTwo() {
      Assert.assertEquals(type != -1, true);
      System.out.println("TestClass.testTwo()");
   }
}

Every time when testOne is invoked with the mocked data after it testTwo must be invoked also: Resutlt -> TestClass.testOne() TestClass.testOne() TestClass.testTwo()

Expected result -> TestClass.testOne() TestClass.testTwo() TestClass.testOne() TestClass.testTwo()

This is my suite xml

    <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" group-by-instances="true">
  <test name="Test" verbose="3" group-by-instances="true" >
    <classes>

      <class name="demo.test.src.TestClass">

      </class>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->

Solution

  • You basically need a Factory coupled with a data provider for getting this done.

    Here's a sample of how it can look like :

    public class TestClass {
    
        private int type = - 1;
        private String name;
    
        @Factory (dataProvider = "mock")
        public TestClass(int type, String name) {
            this.type = type;
            this.name = name;
        }
    
        @DataProvider
        public static Object[][] mock() {
            return new Object[][] {{1, "Hello"}, {2, "World"}};
        }
    
        @Test (groups = {"A"})
        public void testOne() {
            System.out.println("TestClass.testOne()");
            switch (type) {
                case 1:
                    type = 1;
                    Assert.assertEquals(name, "Hello");
                    break;
                case 2:
                    type = 2;
                    Assert.assertEquals(name, "World");
                    break;
                default:
                    break;
            }
        }
    
        @Test (groups = {"A"}, dependsOnMethods = "testOne")
        public void testTwo() {
            Assert.assertEquals(type != - 1, true);
            System.out.println("TestClass.testTwo()");
        }
    }
    

    You then make use of a TestNG suite xml file that leverages group-by-instances attribute (a sample is shown below)

    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
    <suite name="factory-suite"  verbose="2" group-by-instances="true" >
        <test name="factory-test">
            <classes>
                <class name="org.rationale.emotions.TestClass"/>
            </classes>
        </test>
    </suite>