TestNG指定测试特定的Method

发布时间 2023-04-14 21:27:49作者: luzemin

背景

被测试的项目有很多模块,每个模块可能会测试多中动作,动作可能需要测试正向的,也可能会测试负向的。
所以,每个测试类中会存在多个测试方法。

测试指定的方法

很容易想到,通过xml配置

<test name="Regression1">
  <classes>
    <class name="test.IndividualMethodsTest">
      <methods>
        <include name="testMethod1" />
        <exclude name="testMethod2" />
      </methods>
    </class>
  </classes>
</test>

问题

因为method属于某class,所以要首先指定class name。
如果我们需要动态的指定,只运行某个method呢?比如Jenkins运行的时候,我们传入Menthod名称(case 名称)运行特定的case。
使用默认的配置是不行的,class name不允许通配符的。

办法

那如何才能又使用xml配置,又不用指定class name去运行特定的method呢?
我们把目光放在了groups标签上
每个test method可以属于多个group,那我们让每个method属于{method name} group,就是不是可以通过指定group name去运行特定的method的呢?

实现

  1. 方案一
    人工给每个方法增加groups注解
public class Test1 {
  @Test(groups = { "testMethod1", "p0" })
  public void testMethod1() {
  }
 
  @Test(groups = {"testMethod2", "p0"} )
  public void testMethod2() {
  }
 
  @Test(groups = { "testMethod3","p0" })
  public void testMethod3() {
  }
}

可以看到,虽然对于不同的method设置的group的不同的,但是做这个事情的逻辑是相同的,算法是通用的。
所以一定会有一个办法,在某个入口处统一设置。

  1. 方案二
    使用IAnnotationTransformer
    TestNG运行你在运行时修改注解(瞧瞧这设计),只要实现IAnnotationTransformer接口即可
public class SetGroupsTransformer implements IAnnotationTransformer {
    @Override
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod, Class<?> occurringClazz) {
        String[] groups = annotation.getGroups();
        String methodName = testMethod.getName();
        if (groups == null || groups.length == 0) {
            annotation.setGroups(new String[]{methodName});
        } else {
            String[] newGroups = new String[groups.length + 1];
            System.arraycopy(groups, 0, newGroups, 0, groups.length);
            newGroups[newGroups.length - 1] = methodName;
            annotation.setGroups(newGroups);
        }
    }
}

代码来自ChatGPT

下一步,应用自定义的Transformer---SetGroupsTransformer
因为项目代码中已经有Listener的调用,所以我们增加到Listener列表

@Listeners({ com.example.MyListener.class, com.example.SetGroupsTransformer.class })
public class MyTest {
  // ...
}

好家伙,不起作用,transform方法压根不会调用
那试试通过XML指定?

<suite>
  <listeners>
    <listener class-name="com.example.MyListener" />
    <listener class-name="com.example.SetGroupsTransformer" />
  </listeners>

可以! but why?

为什么IAnnotationTransformer通过@Listener调用不起作用?

这里有类似的疑问

https://github.com/cbeust/testng/issues/446

可以看到有人给指路到官方文档了

The @Listeners annotation can contain any class that extends org.testng.ITestNGListener except IAnnotationTransformer and IAnnotationTransformer2. 
The reason is that these listeners need to be known very early in the process so that TestNG can use them to rewrite your annotations, 
therefore you need to specify these listeners in your testng.xml file.

Ref

https://testng.org/doc/documentation-main.html
https://github.com/cbeust/testng/issues/446