TestNG二开总结 - (3) 开发自己的listener TestListenerAdapter
目录
- 一、基本概念
- 二、主要功能
- 三、使用场景
- 五、更多延伸
- 六、总结
TestListenerAdapter 是 TestNG 测试框架中的一个类,它实现了 ITestListener 接口,用于在测试执行过程中监听各种测试事件。TestListenerAdapter 提供了一种方便的方式来扩展 TestNG 的测试监听功能,而无需从头开始实现 ITestListener 接口中的所有方法。以下是对 TestListenerAdapter 的详细解读:
一、基本概念
TestNG:TestNG 是一个强大的、灵活的测试框架,用于Java编程语言的测试。它提供了丰富的注解和配置选项,使得测试代码的编写和执行变得更加简单和高效。
ITestListener:这是 TestNG 中的一个接口,定义了测试监听器需要实现的方法。这些方法在测试执行的不同阶段被调用,允许开发者在测试执行过程中插入自定义的逻辑。
TestListenerAdapter:作为 ITestListener 接口的一个实现类,TestListenerAdapter 提供了空方法(即默认不做任何事情的方法)的实现。这使得开发者可以只覆盖自己感兴趣的方法,而不必实现接口中的所有方法。
二、主要功能
TestListenerAdapter 主要用于监听测试执行过程中的以下事件:
测试开始和结束:
onStart(ITestContext context): 当测试套件开始执行时调用。
onFinish(ITestContext context): 当测试套件结束执行时调用。
测试方法开始和结束:
onTestStart(ITestResult result): 当测试方法开始执行时调用。
onTestSuccess(ITestResult result): 当测试方法成功执行时调用。
onTestFailure(ITestResult result): 当测试方法执行失败时调用。
onTestSkipped(ITestResult result): 当测试方法被跳过时调用。
其他事件(取决于 TestNG 的版本和配置):
还可能包括其他事件,如测试类的开始和结束、测试方法的异常处理等。
三、使用场景
TestListenerAdapter 的使用场景非常广泛,包括但不限于:
日志记录:在测试执行过程中记录详细的日志信息,以便于后续的问题分析和调试。
性能监控:监控测试执行的时间和资源消耗,评估测试的性能表现。
截图和报告:在测试失败时自动截取屏幕截图,并生成详细的测试报告。
数据清理:在测试执行前后清理测试数据,确保测试的独立性和准确性。
#四、示例代码
以下是一个简单的 TestListenerAdapter 示例,展示了如何记录测试方法的成功和失败信息:
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;public class MyTestListener extends TestListenerAdapter {@Overridepublic void onTestSuccess(ITestResult tr) {System.out.println("Test " + tr.getName() + " succeeded");}@Overridepublic void onTestFailure(ITestResult tr) {System.out.println("Test " + tr.getName() + " failed: " + tr.getThrowable());}// ... 还可以继续重写 onTestStart onTestSkipped onTestFailedButWithinSuccessPercentage onTestFailedWithTimeout onStart onFinish
}
然后,你需要在 testng.xml 文件中配置这个监听器,以便 TestNG 在执行测试时能够识别并使用它。
五、更多延伸
其实除了上述的测试阶段延伸方法外 TestListenerAdapter 还有其他用处,了解设计模式的同学不难看出 TestListenerAdapter 命名上明显使用了 Adapter 适配器模式,那既然这样命名了那必然该有适配器的方法不是 那观看代码好像也没有找到蛛丝马迹 那我们不妨向上翻一下
以下为源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.testng;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.testng.collections.Objects;
import org.testng.internal.IResultListener2;public class TestListenerAdapter implements IResultListener2 {private Collection<ITestNGMethod> m_allTestMethods = new ConcurrentLinkedQueue();private Collection<ITestResult> m_passedTests = new ConcurrentLinkedQueue();private Collection<ITestResult> m_failedTests = new ConcurrentLinkedQueue();private Collection<ITestResult> m_skippedTests = new ConcurrentLinkedQueue();private Collection<ITestResult> m_failedButWSPerTests = new ConcurrentLinkedQueue();private final Collection<ITestContext> m_testContexts = new ConcurrentLinkedQueue();private final Collection<ITestResult> m_failedConfs = new ConcurrentLinkedQueue();private final Collection<ITestResult> m_skippedConfs = new ConcurrentLinkedQueue();private final Collection<ITestResult> m_passedConfs = new ConcurrentLinkedQueue();private final Collection<ITestResult> m_timedOutTests = new ConcurrentLinkedQueue();public TestListenerAdapter() {}public void onTestSuccess(ITestResult tr) {this.m_allTestMethods.add(tr.getMethod());this.m_passedTests.add(tr);}public void onTestFailure(ITestResult tr) {this.m_allTestMethods.add(tr.getMethod());this.m_failedTests.add(tr);}public void onTestSkipped(ITestResult tr) {this.m_allTestMethods.add(tr.getMethod());this.m_skippedTests.add(tr);}public void onTestFailedWithTimeout(ITestResult tr) {this.m_allTestMethods.add(tr.getMethod());this.m_timedOutTests.add(tr);this.onTestFailure(tr);}public void onTestFailedButWithinSuccessPercentage(ITestResult tr) {this.m_allTestMethods.add(tr.getMethod());this.m_failedButWSPerTests.add(tr);}protected ITestNGMethod[] getAllTestMethods() {return (ITestNGMethod[])this.m_allTestMethods.toArray(new ITestNGMethod[0]);}public void onStart(ITestContext testContext) {this.m_testContexts.add(testContext);}public void onFinish(ITestContext testContext) {}public List<ITestResult> getFailedButWithinSuccessPercentageTests() {return new ArrayList(this.m_failedButWSPerTests);}public List<ITestResult> getFailedTests() {return new ArrayList(this.m_failedTests);}public List<ITestResult> getPassedTests() {return new ArrayList(this.m_passedTests);}public List<ITestResult> getSkippedTests() {return new ArrayList(this.m_skippedTests);}public Collection<ITestResult> getTimedoutTests() {return new ArrayList(this.m_timedOutTests);}public void setAllTestMethods(List<ITestNGMethod> allTestMethods) {this.m_allTestMethods = allTestMethods;}public void setFailedButWithinSuccessPercentageTests(List<ITestResult> failedButWithinSuccessPercentageTests) {this.m_failedButWSPerTests = failedButWithinSuccessPercentageTests;}public void setFailedTests(List<ITestResult> failedTests) {this.m_failedTests = failedTests;}public void setPassedTests(List<ITestResult> passedTests) {this.m_passedTests = passedTests;}public void setSkippedTests(List<ITestResult> skippedTests) {this.m_skippedTests = skippedTests;}public void onTestStart(ITestResult result) {}public List<ITestContext> getTestContexts() {return new ArrayList(this.m_testContexts);}public List<ITestResult> getConfigurationFailures() {return new ArrayList(this.m_failedConfs);}public void onConfigurationFailure(ITestResult itr) {this.m_failedConfs.add(itr);}public List<ITestResult> getConfigurationSkips() {return new ArrayList(this.m_skippedConfs);}public void beforeConfiguration(ITestResult tr) {}public void onConfigurationSkip(ITestResult itr) {this.m_skippedConfs.add(itr);}public void onConfigurationSuccess(ITestResult itr) {this.m_passedConfs.add(itr);}public String toString() {return Objects.toStringHelper(this.getClass()).add("passed", this.getPassedTests().size()).add("failed", this.getFailedTests().size()).add("skipped", this.getSkippedTests().size()).toString();}
}
package org.testng.internal;import org.testng.IConfigurationListener;public interface IResultListener2 extends IResultListener, IConfigurationListener {
}
其实现了 IResultListener2 接口,而 IResultListener2 接口实现了 IResultListener, IConfigurationListener,其实 是从IResultListener2 接口继承来了 接口适配器的 模式,固作者如此命名。
接下来看 IConfigurationListener 源码 所以不难看出适配动作 其不仅可以在不通过测试结果状态下做处理,还将 测试配置和测试状态两个接口做了适配 我们可以通过继承重写 来在动态的更改config 或者 根据config在不同测试状态下做定制化处理。(这暂不写demo验证了,验简单demo无法从集成测试层做验证只能做单测无意义,写个框架还小题大做 后续分享架构设计的文章再展开demo)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.testng;public interface IConfigurationListener extends ITestNGListener {default void onConfigurationSuccess(ITestResult tr) {}default void onConfigurationSuccess(ITestResult tr, ITestNGMethod tm) {}default void onConfigurationFailure(ITestResult tr) {}default void onConfigurationFailure(ITestResult tr, ITestNGMethod tm) {}default void onConfigurationSkip(ITestResult tr) {}default void onConfigurationSkip(ITestResult tr, ITestNGMethod tm) {}default void beforeConfiguration(ITestResult tr) {}default void beforeConfiguration(ITestResult tr, ITestNGMethod tm) {}
}
六、总结
TestListenerAdapter 是 TestNG 测试框架中一个非常有用的类,它提供了一种方便的方式来监听测试执行过程中的各种事件,并在这些事件发生时执行自定义的逻辑。通过扩展 TestListenerAdapter,开发者可以轻松地实现日志记录、性能监控、截图和报告等功能,从而提高测试的质量和效率。