一.注解变压器
TestNG允许在执行期间修改所有注解的内容。当源代码中的注解大部分是正确的,但是有一些时刻你想要重写他们的值时,这个是非常有用的。
可以使用注解变压器实现。
注解变压器是一个实现了接口的类:
public interface IAnnotationTransformer { /** * This method will be invoked by TestNG to give you a chance * to modify a TestNG annotation read from your test classes. * You can change the values you need by calling any of the * setters on the ITest interface. * * Note that only one of the three parameters testClass, * testConstructor and testMethod will be non-null. * * @param annotation The annotation that was read from your * test class. * @param testClass If the annotation was found on a class, this * parameter represents this class (null otherwise). * @param testConstructor If the annotation was found on a constructor, * this parameter represents this constructor (null otherwise). * @param testMethod If the annotation was found on a method, * this parameter represents this method (null otherwise). */ public void transform(ITest annotation, Class testClass, Constructor testConstructor, Method testMethod);}
就像所有其他的TestNG监听者,你可以在命令行或使用ant来定义这个类:
java org.testng.TestNG -listener MyTransformer testng.xml
或编程式方式:
TestNG tng = new TestNG();tng.setAnnotationTransformer(new MyTransformer());// ...
当调用transform()方法时,可以调用ITest测试参数上任何设置方法来修改其值,然后再继续测试。
例如,下面是一个如何重写属性的调用次数的例子,但是仅在测试类的测试方法的invoke()上:
public class MyTransformer implements IAnnotationTransformer { public void transform(ITest annotation, Class testClass, Constructor testConstructor, Method testMethod){ if ("invoke".equals(testMethod.getName())) { annotation.setInvocationCount(5); } }}
IAnnotationTransfomer只允许修改@Test注解,如果需要修改其他TestNG注解(配置注解,如@Factory或@DataProvider),需要使用IAnnotationTransformer2。
二.方法拦截器
一旦TestNG计算出测试方法的调用顺序,这些方法将被分成两组:
1)方法按照顺序执行,这些都是有依赖项或被依赖项的所有测试方法,这些测试方法将会按照特定的顺序执行。
2)方法没有特定的执行顺序,这些都是不属于第一类的方法。这些测试方法的运行顺序是随机的,每次运行时的顺序都可能会不同(默认情况下,TestNG将按照类对测试方法进行分组)。
为了更好的控制第二类方法的执行,TestNG定义了下面这些接口:
public interface IMethodInterceptor { List intercept(List methods, ITestContext context);}
参数中传递的方法列表是可以按照任何顺序运行的所有方法。拦截器将会返回一个类型的IMethodInstance列表,可以是以下任意一种:
1)一个更小的IMethodInstance对象列表。
2)一个更大的IMethodInstance对象列表。
3)一旦已定义了拦截器,就将它传递给TestNG作为一个监听者,例如:
java -classpath "testng-jdk15.jar:test/build" org.testng.TestNG -listener test.methodinterceptors.NullMethodInterceptor
-testclass test.methodinterceptors.FooTest
有关ant的有效语法,可以参考ant文档中的listeners属性。
例如,下面是一个方法拦截器,它将对方法重新排序,以便始终首先运行属于组“fast”的测试方法:
public Listintercept(List methods, ITestContext context) { List result = new ArrayList(); for (IMethodInstance m : methods) { Test test = m.getMethod().getConstructorOrMethod().getAnnotation(Test.class); Set groups = new HashSet(); for (String group : test.groups()) { groups.add(group); } if (groups.contains("fast")) { result.add(0, m); } else { result.add(m); } } return result;}