接口自动化测试的必备~ 更多测开知识和技能,还有面经相关,查看公众号【测试备忘录】
1. BeanShell和高级组选择
如果testng.xml中的<include>和<exclude>标记不足以满足需要,则可以使用BeanShell表达式来确定是否应在测试运行中包含某种测试方法。可以在<test>标记下指定此表达式:
<test name="BeanShell test"><method-selectors><method-selector><script language="beanshell"><![CDATA[groups.containsKey("test1")]]></script></method-selector></method-selectors><!-- ... -->
当在testng.xml中找到<script>标记时,TestNG将忽略当前<test>标记中随后的组和方法的<include>和<exclude>:BeanShell表达式将唯一决定一个测试方法是否包含在内。
有关BeanShell脚本的一些其他信息:
-
返回值必须返回一个布尔值。除此之外,允许使用任何有效的BeanShell代码(例如,你可能希望在工作日返回true,而在周末返回false,这将允许你根据日期以不同的方式运行测试)。
-
为了方便起见,TestNG定义了以下变量:
-
java.lang.reflect.Method方法:当前的测试方法。
-
org.testng.ITestNGMethod testngMethod:当前测试方法的描述。
-
java.util.Map <String,String> groups:当前测试方法所属的组的映射。
-
-
通过用CDATA声明包围表达式(如上所示),以避免冗长的保留XML字符引用。
2. 注解的转换
TestNG允许您在运行时修改所有注解的内容。 通常的使用情况是:注解大多数时候无需修改,仅在在某些需要的情况下,需要覆盖它们的值。为了实现这个目的,需要使用注解转换器(Annotation Transformer)。
Annotation Transformer是一个实现以下接口的类:
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()时,可以在TestNG进程运行之前,调用ITest测试参数上的任何设置方法来更改其值。
以下面的示例说明,示例是如何重写属性invocationCount的方法,在仅调用其中一个测试类的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);}}}
IAnnotationTransformer仅允许修改一个@Test注解。如果需要修改另一个TestNG注解(配置注解@Factory或@DataProvider等),需要使用IAnnotationTransformer2。
3. 方法拦截器
一旦TestNG计算了测试方法将被调用的顺序,这些方法将分为两组:
-
按顺序运行的方法。这些都是具有依赖项或依赖项的测试方法。这些方法将以特定顺序运行。
-
没有特定的运行顺序的方法。这些都是不属于第一类的方法。这些测试方法的运行顺序是随机的,一次运行到下一次运行可能会有所不同(尽管默认情况下,TestNG会尝试按类对测试方法进行分组)。
为了能够更好地控制属于第二类的方法,TestNG定义了以下接口:
public interface IMethodInterceptor {List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context);}
传入的方法列表参数是可以按任何顺序运行的所有方法。预期的拦截方法将返回类似的IMethodInstance列表,该列表可以是以下任意一种:
-
与传入参数的方法列表相同,但顺序不同。
-
比IMethodInstance列表规模小一些的方法列表。
-
比IMethodInstance列表规模大一些的方法列表。
定义拦截器后,将其作为监听器传递给TestNG。例如:
java -classpath "testng-jdk15.jar:test/build" org.testng.TestNG -listener test.methodinterceptors.NullMethodInterceptor-testclass test.methodinterceptors.FooTest
一个方法拦截器示例,它将对方法进行重新排序,始终首先运行属于“快速”组的测试方法:
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {List<IMethodInstance> result = new ArrayList<IMethodInstance>();for (IMethodInstance m : methods) {Test test = m.getMethod().getConstructorOrMethod().getAnnotation(Test.class);Set<String> groups = new HashSet<String>();for (String group : test.groups()) {groups.add(group);}if (groups.contains("fast")) {result.add(0, m);}else {result.add(m);}}return result;}
欢迎关注我的微信公众号 【测试备忘录】,查看更多测开技能知识。一起学习交流~
1121





