TestNG - Run each instance from TestNG factory as separate test

1.4k Views Asked by At

I am using TestNG for test automation along with ReportNG for reporting. I use a TestNG factory class to provide different inputs for my tests. The problem which I face here is that all test instances supplied by the factory run under the same test, and the report generated displays all the scenarios under a single test.

I want to run each test instance supplied by the factory as a separate test. Is there any way to do this? PFB my xml configuration

<suite name="Default suite" parallel="classes">
<listeners>
         <listener class-name="org.uncommons.reportng.HTMLReporter" />
</listeners>
<test verbose="2" name="Default test" group-by-instances="true">
    <classes>
        <class name="com.test.factory.RAExcelFactory"/> 
    </classes>
  </test> <!-- Default test -->
</suite> <!-- Default suite -->
1

There are 1 best solutions below

3
On

No this is not possible currently in TestNG.

Alternately you can consider doing the following instead of using a factory.

  • Upgrade to latest TestNG version
  • Build an implementation of org.testng.IAlterSuiteListener and within it include logic to construct multiple <test> tags by using whatever logic you have within your Factory (am guessing it leverages a data driven mechanism)

Something like below

Test Class

import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class StudentTest {
    private int age;
    @BeforeClass
    @Parameters("age")
    public void setup(int age) {
        this.age = age;
    }

    @Test
    public void firstTest() {
        Assert.assertTrue(age >=0);
    }

    @Test(dependsOnMethods = "firstTest")
    public void secondTest() {
        Assert.assertTrue(age <= 125);
    }
}

An IAlterSuiteListener implementation

import org.testng.IAlterSuiteListener;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;

import java.util.ArrayList;
import java.util.List;

public class SuiteAlteringListener implements IAlterSuiteListener {
    @Override
    public void alter(List<XmlSuite> suites) {
        for (XmlSuite suite : suites) {
            List<XmlTest> tests = new ArrayList<>();
            Integer[] datum = getData();
            for (Integer data : datum) {
                XmlTest test = new XmlTest(suite);
                test.setName("test_" + data);
                test.addParameter("age", Integer.toString(data));
                test.getClasses().add(new XmlClass(StudentTest.class));
            }
        }
    }

    private Integer[] getData() {
        //Change this to your data provider implementation
        return new Integer[]{
                1, 2, 3
        };
    }
}

The suite xml file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="my_suite" parallel="false" verbose="3">
    <listeners>
        <listener class-name="com.rationaleemotions.stackoverflow.SuiteAlteringListener"/>
    </listeners>

</suite>

and here's how the testng-results.xml looks like (The other reports would have similar details as well). I am just choosing to attach the easiest representation.

<?xml version="1.0" encoding="UTF-8"?>
<testng-results skipped="0" failed="0" ignored="0" total="6" passed="6">
  <reporter-output>
  </reporter-output>
  <suite name="my_suite" duration-ms="10077" started-at="2017-05-27T07:49:36Z" finished-at="2017-05-27T07:49:46Z">
    <groups>
    </groups>
    <test name="test_1" duration-ms="24" started-at="2017-05-27T07:49:36Z" finished-at="2017-05-27T07:49:36Z">
      <class name="com.rationaleemotions.stackoverflow.StudentTest">
        <test-method status="PASS" signature="setup(int)[pri:0, instance:com.rationaleemotions.stackoverflow.StudentTest@61dc03ce]" name="setup" is-config="true" duration-ms="8" started-at="2017-05-27T13:19:36Z" finished-at="2017-05-27T13:19:36Z">
          <params>
            <param index="0">
              <value>
                <![CDATA[1]]>
              </value>
            </param>
          </params>
          <reporter-output>
          </reporter-output>
        </test-method> <!-- setup -->
        <test-method status="PASS" signature="firstTest()[pri:0, instance:com.rationaleemotions.stackoverflow.StudentTest@61dc03ce]" name="firstTest" duration-ms="2" started-at="2017-05-27T13:19:36Z" finished-at="2017-05-27T13:19:36Z">
          <reporter-output>
          </reporter-output>
        </test-method> <!-- firstTest -->
        <test-method status="PASS" signature="secondTest()[pri:0, instance:com.rationaleemotions.stackoverflow.StudentTest@61dc03ce]" name="secondTest" duration-ms="1" started-at="2017-05-27T13:19:36Z" depends-on-methods="com.rationaleemotions.stackoverflow.StudentTest.firstTest" finished-at="2017-05-27T13:19:36Z">
          <reporter-output>
          </reporter-output>
        </test-method> <!-- secondTest -->
      </class> <!-- com.rationaleemotions.stackoverflow.StudentTest -->
    </test> <!-- test_1 -->
    <test name="test_2" duration-ms="2" started-at="2017-05-27T07:49:41Z" finished-at="2017-05-27T07:49:41Z">
      <class name="com.rationaleemotions.stackoverflow.StudentTest">
        <test-method status="PASS" signature="setup(int)[pri:0, instance:com.rationaleemotions.stackoverflow.StudentTest@458ad742]" name="setup" is-config="true" duration-ms="0" started-at="2017-05-27T13:19:41Z" finished-at="2017-05-27T13:19:41Z">
          <params>
            <param index="0">
              <value>
                <![CDATA[2]]>
              </value>
            </param>
          </params>
          <reporter-output>
          </reporter-output>
        </test-method> <!-- setup -->
        <test-method status="PASS" signature="firstTest()[pri:0, instance:com.rationaleemotions.stackoverflow.StudentTest@458ad742]" name="firstTest" duration-ms="0" started-at="2017-05-27T13:19:41Z" finished-at="2017-05-27T13:19:41Z">
          <reporter-output>
          </reporter-output>
        </test-method> <!-- firstTest -->
        <test-method status="PASS" signature="secondTest()[pri:0, instance:com.rationaleemotions.stackoverflow.StudentTest@458ad742]" name="secondTest" duration-ms="0" started-at="2017-05-27T13:19:41Z" depends-on-methods="com.rationaleemotions.stackoverflow.StudentTest.firstTest" finished-at="2017-05-27T13:19:41Z">
          <reporter-output>
          </reporter-output>
        </test-method> <!-- secondTest -->
      </class> <!-- com.rationaleemotions.stackoverflow.StudentTest -->
    </test> <!-- test_2 -->
    <test name="test_3" duration-ms="2" started-at="2017-05-27T07:49:46Z" finished-at="2017-05-27T07:49:46Z">
      <class name="com.rationaleemotions.stackoverflow.StudentTest">
        <test-method status="PASS" signature="setup(int)[pri:0, instance:com.rationaleemotions.stackoverflow.StudentTest@66d2e7d9]" name="setup" is-config="true" duration-ms="0" started-at="2017-05-27T13:19:46Z" finished-at="2017-05-27T13:19:46Z">
          <params>
            <param index="0">
              <value>
                <![CDATA[3]]>
              </value>
            </param>
          </params>
          <reporter-output>
          </reporter-output>
        </test-method> <!-- setup -->
        <test-method status="PASS" signature="firstTest()[pri:0, instance:com.rationaleemotions.stackoverflow.StudentTest@66d2e7d9]" name="firstTest" duration-ms="0" started-at="2017-05-27T13:19:46Z" finished-at="2017-05-27T13:19:46Z">
          <reporter-output>
          </reporter-output>
        </test-method> <!-- firstTest -->
        <test-method status="PASS" signature="secondTest()[pri:0, instance:com.rationaleemotions.stackoverflow.StudentTest@66d2e7d9]" name="secondTest" duration-ms="0" started-at="2017-05-27T13:19:46Z" depends-on-methods="com.rationaleemotions.stackoverflow.StudentTest.firstTest" finished-at="2017-05-27T13:19:46Z">
          <reporter-output>
          </reporter-output>
        </test-method> <!-- secondTest -->
      </class> <!-- com.rationaleemotions.stackoverflow.StudentTest -->
    </test> <!-- test_3 -->
  </suite> <!-- my_suite -->
</testng-results>

Would this work for you ?