1
votes

I want to set group to a particular @Test method at runtime depending on some condition

Suppose I have the following classes

public class MyTest1{
  @Test
  public void test1(){
    System.out.println("test1 called");
  }
}

public class MyTest2{
  @Test(groups={"group1"})
  public void test2(){
    System.out.println("test2 called");
  }

  @Test(groups={"group2"})
  public void test3(){
    System.out.println("test3 called");
  }
}

Now while running test I am sending "-groups group1" or "-groups group2" to TestNG in command line. So testng is running either test2() or test3() depending on the group name passed. Now my requirement is to run test1() that is not supposed have any groups attached. Whatever group I provide to testng runner this test1() should be run every time. I tried with implementing alter method of IAlterSuiteListener but I could not get all the test methods including which are not considered to run. So I could not set the group name at runtime.

So is there any other way to set groups to @Test methods (having no groups defined) at runtime?

2

2 Answers

2
votes

You should perhaps start exploring the beanshell way of method selection that TestNG provides to you for this purpose.

Sometime back I wrote up a blog post which talks about how to work with Beanshell expressions in TestNG. You can read more about it here and refer to the official TestNG documentation here.

Quoting the TestNG documentation,

TestNG defines the following variables for your convenience:

  • java.lang.reflect.Method method: the current test method.
  • org.testng.ITestNGMethod testngMethod: the current test method.
  • java.util.Map groups: a map of the groups the current test method belongs to.

So with just your example, I went ahead to create a suite xml file that looks like below

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="1265_Suite" parallel="false" verbose="2">
    <test name="92" parallel="false" preserve-order="true">
        <method-selectors>
            <method-selector>
                <script language="beanshell">
                    <![CDATA[whatGroup = System.getProperty("groupToRun");
                (groups.containsKey(whatGroup) || testngMethod.getGroups().length ==0);
                ]]>
                </script>
            </method-selector>
        </method-selectors>
        <classes>
            <class name="com.rationaleemotions.stackoverflow.MyTest1"/>
            <class name="com.rationaleemotions.stackoverflow.MyTest2"/>
        </classes>
    </test>
</suite>

And I run it via the command prompt using maven as below : (The test classes are basically what you shared in your question )

mvn clean test -DsuiteXmlFile=dynamic_groups.xml -DgroupToRun=group2

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running TestSuite
...
... TestNG 6.11 by Cédric Beust ([email protected])
...

test1 called
test3 called
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 15.377 sec - in TestSuite

Results :

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
0
votes

There is no direct way of doing this if you are specifying groups. However, there are two other ways of doing this.

  1. You can mark all your tests with no groups in a group called "nogroups" and include that group while you run Or
  2. If you have huge number of tests that you already have, then write up an Annotation Transformer which basically adds cases with no groups in this group --sample example below. Writing a transformer can help you control edge cases programmatically as well.

public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { if (annotation.getGroups().length == 0) { annotation.setGroups(new String[]{"noGroups"}); } }