Invoke different classed based on the parameter provided in testng.XML

1k views Asked by At
I have a query regarding testng module. My requirement is to invoke different classes based on the parameter provided in the testng.xml

Testng.XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<parameter name="selenium.test" value="Web" />
  <parameter name="selenium.testtype" value="Sanity" />
  <parameter name="selenium.env" value="UAT" />
  <parameter name="selenium.browser" value="IE" />
  <parameter name="selenium.pbrowser" value="Mozilla" />

  <test name =>
    <classes>
      <class name="test.DriverTest"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->

1) In the above code snippet, if my test type is sanity, I want to invoke Sanity.java file where as if other test type is regression, I want to invoke Regression.java

2) Can we pass parameter value as input to other XML tags in testng.xml Example: If then i want this value to feeded dyanamically based on parameter value

3) Also from this parameter input how to invoke parallel browser testing?

1

There are 1 answers

0
Krishnan Mahadevan On BEST ANSWER

1) In the above code snippet, if my test type is sanity, I want to invoke Sanity.java file where as if other test type is regression, I want to invoke Regression.java

TestNG provides you with a concept called groups which should solve this for you. For every @Test method, add the groups attribute to it and then, in your suite xml file, you can pick and choose whichever groups you would like to run. Refer the official documentation here for more information.

2) Can we pass parameter value as input to other XML tags in testng.xml Example: If then i want this value to feeded dyanamically based on parameter value

Not sure what you are after here, but the parameters in a testng suite xml file are always static in nature. They cannot be changed unless and until you alter the suite xml file (or) you make use of a TestNG listener such as org.testng.IAlterSuiteListener wherein you fudge the parameters based on some thing else. Here's a sample that shows what I am talking about

A test class which expects a parameter to be injected

package com.rationaleemotions.stackoverflow.qn46216357;

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

public class SampleTestClass {

    @Test
    @Parameters("name")
    public void testMethod(String name) {
        System.err.println("Hello " + name);
    }
}

This listener looks for JVM arguments that begin with jvm_ and whose name matches with the parameters in the suite xml and if found, it updates the parameter value with what was sent in the JVM argument. So using this way, you can literally achieve what you are after.

package com.rationaleemotions.stackoverflow.qn46216357;

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

import java.util.List;
import java.util.Map;

public class ParameterChangerListener implements IAlterSuiteListener {
    @Override
    public void alter(List<XmlSuite> suites) {
        XmlSuite suite = suites.get(0);

        for (Map.Entry<String, String> each : suite.getParameters().entrySet()) {
            //Check to see if we were given any JVM arguments with the prefix as "jvm_" followed
            //by the text of the parameter name.
            String sysValue = System.getProperty("jvm_" + each.getKey());
            if (sysValue != null && !sysValue.trim().isEmpty()) {
                each.setValue(sysValue);
            }
        }
    }
}

Here's how the suite xml looks like

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="46216357_Suite" verbose="2">
    <listeners>
        <listener class-name="com.rationaleemotions.stackoverflow.qn46216357.ParameterChangerListener"/>
    </listeners>
    <parameter name="name" value="Unknown"/>
    <test name="46216357_test">
        <classes>
            <class name="com.rationaleemotions.stackoverflow.qn46216357.SampleTestClass"/>
        </classes>
    </test>
</suite>

As you can see, I have defined a value of Unknown for the parameter name

So if you just right click on the suite xml and run it from your favorite IDE, the output would look like below:

...
... TestNG 6.12 by Cédric Beust ([email protected])
...
Hello Unknown
PASSED: testMethod("Unknown")

===============================================
    46216357_test
    Tests run: 1, Failures: 0, Skips: 0
===============================================

===============================================
46216357_Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

But if you run the same suite, by passing in the JVM argument -Djvm_name, then the output would be different. Here's a run output wherein I am passing in the value as Rambo : -Djvm_name=Rambo

...
... TestNG 6.12 by Cédric Beust ([email protected])
...
Hello Rambo
PASSED: testMethod("Rambo")

===============================================
    46216357_test
    Tests run: 1, Failures: 0, Skips: 0
===============================================

===============================================
46216357_Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

3) Also from this parameter input how to invoke parallel browser testing?

I would alter this a bit and instead suggest that you read the parallel mode as a JVM argument and based on that change your parallel execution strategy. You basically employ the same sort of a IAlterSuiteListener implementation as I shared above and it could look like below :

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

import java.util.List;

public class ParallelExecutorSetter implements IAlterSuiteListener {
    @Override
    public void alter(List<XmlSuite> suites) {
        XmlSuite suite = suites.get(0);
        String parallelMode = System.getProperty("parallelMode");
        XmlSuite.ParallelMode mode = XmlSuite.ParallelMode.getValidParallel(parallelMode);
        if (mode != null) {
            suite.setParallel(mode);
        }
    }
}

So you can now change your parallel mode by passing it via the JVM argument. For e.g., -DparallelMode=methods to run all your @Test methods in parallel