Frage

I know you can define in your xml which groups that you want to run, but I want to know whether it is possible to say run these methods if they are both member of groups A & B.

Let's say I have the following test cases;

@Test(groups={"A","B"})
public testA() {}

@Test(groups={"B","C"})
public testB(){}

and following configuration;

<test name="Test A|B">
<groups>
       <run>
           <include name="B" />
       </run>
    </groups>

    <classes>
        <class name="com.test.Test" />
    </classes>
</test>

This will run both testA and testB since they are both members of group B. I want to run the test only if it is member of both groups A & B.

Is it possible to do such thing with TestNG?

Thanks in advance

War es hilfreich?

Lösung

You can create a listener implementing IMethodInterceptor interface. Which will give you an ability to access groups list from your @Test and manage your "tests to execute list" as you need. At same time ITestContext parameter allows you to access the data from testNg xml. So, you can set groups to run in default testNg manner (suite xml file); but run them depending on algorithm you implement. Something like:

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

import org.testng.IMethodInstance;
import org.testng.IMethodInterceptor;
import org.testng.ITestContext;
import org.testng.annotations.Test;

public class Interceptor implements IMethodInterceptor
{

    @Override
    public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context)
    {
        int methCount = methods.size();
        List<IMethodInstance> result = new ArrayList<IMethodInstance>();

        for (int i = 0; i < methCount; i++)
        {
            IMethodInstance instns = methods.get(i);
            List<String> grps = Arrays.asList(instns.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class).groups());
//get these groups from testng.xml via context method parameter                         
            if (grps.contains("A") && grps.contains("B"))
            {
                result.add(instns);
            }                       
        }                       
        return result;
    }
}

Andere Tipps

You can do this with the TestNG beanshell support: http://testng.org/doc/documentation-main.html#beanshell (you are getting access to method, testngMethod, and groups)

In your particular case, it would be something like this:

<method-selectors>
  <method-selector>
    <script language="beanshell"><![CDATA[
       return groups.containsKey("A") && groups.containsKey("B");
     ]]></script>
  </method-selector>
</method-selectors>

You could also do a System.out.println() if you wanted to debug stuff.

The catch here is that you need to define the "method-selectors" in the "test" block. For some reason, if you define the "method-selectors" in "suite" (which is syntactically correct), the filter is not applied.

Debugging this with System.out.println() is going to help you understand whether the stuff even runs, or which methods it filters, so e.g.:

<method-selectors>
  <method-selector>
    <script language="beanshell"><![CDATA[
      runMethod = groups.containsKey("A") && groups.containsKey("B");
      System.out.println("run '" + testngMethod.getMethodName() + "'? -> " + runMethod);
      return runMethod;
    ]]></script>
  </method-selector>
</method-selectors>

Did you try this?

<test name="Test A|B">
<groups>
       <run>
           <include name="A" />
            <include name="B" />
       </run>
    </groups>

    <classes>
        <class name="com.test.Test" />
    </classes>
</test>

If that doesn't work, you can "hack" around it by having 3 test methods in your class (with preserve order turned on) and have the first 2 tests set a flag on a condition, and then then 3rd test only runs if both conditions are set.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top