TestNG监听器
有几个接口可来修改TestNG的行为。这些接口统一称为“ TestNG监听器”。以下是一些监听器:
IAnnotationTransformer IAnnotationTransformer2 IHookable IInvokedMethodListener IMethodInterceptor IReporter ISuiteListener ITestListener
当实现任意一接口时,可以通过以下任意方式传给TestNG:
在命令行上使用-listener。 将<listeners>与ant一起使用。 在您的testng.xml文件中使用<listeners>。 在任何测试类上使用@Listeners批注。 使用ServiceLoader。
1)使用testng.xml或Java指定监听器
在testng.xml文件中定义监听器的方法:
<suite> <listeners> <listener class-name="com.example.MyListener" /> <listener class-name="com.example.MyMethodInterceptor" /> </listeners> ......
java中定义的方式:
@Listeners({ com.example.MyListener.class, com.example.MyMethodInterceptor.class }) public class MyTest { // ... }
@Listeners注解可以包含任何扩展org.testng.ITestNGListener的类,但IAnnotationTransformer和IAnnotationTransformer2除外。原因是这些监听器需要在流程的早期就要介入,以便TestNG可以使用它们来重写注解,因此需要在testng.xml文件中指定这些监听器。
注意,@ Listeners注解将应用于整个suite文件,就像在testng.xml文件中指定的一样。如果要限制其范围(例如,仅在当前类上运行),则监听器中的代码可以首先检查将要运行的测试方法,然后决定要做什么。具体的形式如下:
1)首先定义一个新的自定义注解,用于指定限制范围
@Retention(RetentionPolicy.RUNTIME) @Target ({ElementType.TYPE}) public @interface DisableListener {}
2)在使用的监听器中添加编辑检查项:
public void beforeInvocation(IInvokedMethod iInvokedMethod, ITestResult iTestResult) { ConstructorOrMethod consOrMethod =iInvokedMethod.getTestMethod().getConstructorOrMethod(); DisableListener disable = consOrMethod.getMethod().getDeclaringClass().getAnnotation(DisableListener.class); if (disable != null) { return; } // else resume your normal operations }
3)通过注解指定不调用监听器的测试类:
@DisableListener @Listeners({ com.example.MyListener.class, com.example.MyMethodInterceptor.class }) public class MyTest { // ... }
2)使用ServiceLoader指定监听器
JDK提供了一种非常优雅的机制,可以通过ServiceLoader类在类路径上指定接口的实现。
使用ServiceLoader,要做的就是创建一个包含监听器和一些配置文件的jar文件,在运行TestNG时将该jar文件放在类路径中,TestNG会自动找到它们。
以下是工作方式的具体示例:
- 创建一个监听器(任意testNG的监听器都可以)
package test.tmp; public class TmpSuiteListener implements ISuiteListener { @Override public void onFinish(ISuite suite) { System.out.println("Finishing"); } @Override public void onStart(ISuite suite) { System.out.println("Starting"); } }
- 编译该文件,然后在META-INF / services / org.testng.ITestNGListener位置创建一个文件,将该文件命名为这个接口的实现,例如示例的TmpSuiteListener。
- 整体目录结构如下:
$ tree |____META-INF | |____services | | |____org.testng.ITestNGListener |____test | |____tmp | | |____TmpSuiteListener.class $ cat META-INF/services/org.testng.ITestNGListener test.tmp.TmpSuiteListener
创建jar包
$ jar cvf ../sl.jar . added manifest ignoring entry META-INF/ adding: META-INF/services/(in = 0) (out= 0)(stored 0%) adding: META-INF/services/org.testng.ITestNGListener(in = 26) (out= 28)(deflated -7%) adding: test/(in = 0) (out= 0)(stored 0%) adding: test/tmp/(in = 0) (out= 0)(stored 0%) adding: test/tmp/TmpSuiteListener.class(in = 849) (out= 470)(deflated 44%)
接下来,在调用TestNG时,将此jar文件放在类路径中:
$ java -classpath sl.jar:testng.jar org.testng.TestNG testng-single.yaml Starting f2 11 2 PASSED: f2("2") Finishing
通过这个机制,只需将jar文件添加到类路径即可将相同的一组监听器应用于整个组织节点,从而不需要要求每个开发人员都记住在其testng.xml文件中指定这些监听器。