10 月 23 - 25 日,QCon 上海站即将召开,现在购票,享9折优惠 了解详情
写点什么

TestNG 测试用例重跑详解及实践优化

  • 2020-05-26
  • 本文字数:4369 字

    阅读完需:约 14 分钟

TestNG测试用例重跑详解及实践优化

测试用例运行稳定性是自动化质量的一个重要指标,在运行中需要尽可能的剔除非 bug 造成的测试用例执行失败,对于失败用例进行重跑是常用策略之一。一种重跑策略是所有用例运行结束后对失败用例重跑,另一种重跑策略是在运行时监控用例运行状态,失败后实时重跑。


下面,详细介绍 TestNG 如何对失败测试用例实时重跑并解决重跑过程中所遇到问题的实践和解决方案。对失败测试用例进行实时重跑,有以下几个方面需求:


  1. 测试用例运行失败,监听到失败后立即进行重跑

  2. 测试用例通过 dependsOnMethods/dependsOnGroups 标记依赖其他测试用例,在被依赖的测试用例重跑运行成功后,该测试用例可以继续运行

  3. 对于重跑多次的测试用例,只记录最后一次运行成功或失败结果

一、测试用例重跑

1.1 retryAnalyzer 注解方式

对于希望测试用例中的少量易失败,不稳定的测试用例进行重跑,可采用这种方式。

1.1.1 原理

以下是 TestNG 处理测试用例运行结果的部分代码。


IRetryAnalyzer retryAnalyzer = testMethod.getRetryAnalyzer();boolean willRetry = retryAnalyzer != null && status == ITestResult.FAILURE && failure.instances != null && retryAnalyzer.retry(testResult);if (willRetry) {  resultsToRetry.add(testResult);  failure.count++;  failure.instances.add(testResult.getInstance());  testResult.setStatus(ITestResult.SKIP);} else {  testResult.setStatus(status);  if (status == ITestResult.FAILURE && !handled) {    handleException(ite, testMethod, testResult, failure.count++);  }
复制代码


分析以上代码,其中,接口 IretryAnalyzer 的方法 retry()的返回值作为是否对失败测试用例进行重跑的一个条件。如果 retry()结果为 true,则该失败测试用例会重跑,同时将本次失败结果修改为 Skip;如果结果为 false,则失败的测试用例保持失败结果,运行结束。因此,如果你希望失败测试用例重跑的话,需要把 IretryAnalyzer 的 retry()方法重写,插入自己定义的逻辑,设置返回值为 true。

1.1.2 代码

创建类 RetryImpl,重写 retry()方法,设置失败测试用例的重跑次数,代码如下:


public class RetryImpl implements IRetryAnalyzer {    private int count = 1;    private int max_count = 3;   // Failed test cases could be run 3 times at most    @Override    public boolean retry(ITestResult result) {        System.out.println("Test case :"+result.getName()+",retry time: "+count+"");        if (count < max_count) {            count++;            return true;        }        return false;    }}
复制代码

1.1.3 实例

public class TestNGReRunDemo {    @Test(retryAnalyzer=RetryImpl.class)    public void test01(){        Assert.assertEquals("success","fail");        System.out.println("test01");    }}
复制代码


以上测试用例 test01 可重复运行 3 次。

1.2 实现接口 IAnnotationTransformer 方式

如果希望所有失败的测试用例都进行重跑,采用 retryAnalyzer 注解方式对每个测试用例进行注解就比较麻烦。通过实现 IAnnotationTransformer 接口的方式,可以对全量测试用例的重试类进行设置。该接口是一个监听器接口,用来修改 TestNG 注解。IAnnotationTransformer 监听器接口只有一个方法:transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod). 上文中,我们自定义了类 RetryImpl 实现接口 IRetryAnalyzer。TestNG 通过 transfrom()方法修改 retryAnalyzer 注解。以下代码对 retryAnalyzer 注解进行修改设置

1.2.1 代码

创建类 RetryListener,代码如下。


public class RetryListener implements IAnnotationTransformer {
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
IRetryAnalyzer retry = annotation.getRetryAnalyzer(); if (retry == null) { annotation.setRetryAnalyzer(RetryImpl.class); } }}
复制代码

1.2.2 配置 Listener

TestNG 可以在配置文件或者测试类中对Listener类进行配置。


  • 方法一:在 TestNG 的配置 XML 中进行以下配置

  • 方法二:在测试类中通过 @Listeners 配置


@Listeners({RetryListener.class})public class TestNGReRunDemo {    @Test    public void test01(){        Assert.assertEquals("success","fail");        System.out.println("test01");    }}
复制代码


配置完成后,运行测试用例 test01,运行结果显示 test01 将重跑次数 3 次。

二、被依赖的测试用例重跑结果处理

进一步分析 TestNG 的运行代码,其在对失败运行用例重跑时,逻辑如下图。



对于通过 dependsOnMethods 或 dependsOnGroups 注解依赖于其他测试用例的测试用例来讲 ,测试用例执行分为两种情况:


  • alwaysRun=true: 则无论所依赖的测试用例执行情况如何,该测试用例都会执行, 即所依赖的测试用例重跑不会影响该测试用例的执行

  • alwaysRun=false: 或者保持缺省值(false),依赖于其他测试用例或测试用例组的测试结果,在运行时 TestNG 获取所依赖的测试用例的运行结果,检查依赖的测试用例是否全部执行成功,如果不全部成功,则 把该测试用例结果设置为 Skipped

2.1 场景分析:场景一

被依赖的测试用例失败后进行了重跑,并重跑成功。(注:在 RetryImpl 类中,已设置最大重跑次数 max_count = 3


public static int number =0;
@Testpublic void test01(){number++;System.out.println(String.valueOf(number));Assert.assertEquals(number,2); System.out.println("test01");}
@Test(dependsOnMethods = "test01") // alwaysRun = false by defaultpublic void test02(){ System.out.println("test02 is running only if test01 is passed.");}
复制代码


1、TestNG 测试报告



2、问题


测试用例运行次数运行情况测试报告
Test012第一次:skipped ; 第二次:passed在Skipped 和Passed的统计数量中,test01被分别记录一次
Test020Skipped记录一次Skipped


  • 测试报告: test01 运行结果全部被记录,而用例重跑,只希望记录最后的结果。

  • 运行情况: 测试用例 test02 依赖于测试用例 test01 运行结果,在 test01 重跑成功后,测试用例 test02 没有执行,不符合需求预期

2.2 场景分析:场景二

被依赖的测试用例失败后进行了重跑,并且重跑没有成功。(注:在 RetryImpl 类中,已设置最大重跑次数 max_count = 3)


public static int number =0;@Testpublic void test01(){number++;System.out.println(String.valueOf(number));Assert.assertEquals(number,10);    System.out.println("test01");}
@Test(dependsOnMethods = "test01") // alwaysRun = false by defaultpublic void test02(){ System.out.println("test02 is running only if test01 is passed.");}
复制代码


1、TestNG 测试报告



2、问题


测试用例运行次数运行结果测试报告
Test013第一次:skipped;第二次:skipped;第三次:failed在Skipped统计数量中,test01被被记录两次在failed统计中,test01被记录一次
Test020Skipped记录一次Skipped


  • 运行情况: 测试用例 test02 依赖于测试用例 test01 运行结果, 在 test01 重跑失败后,测试用例 test02 没有执行,这种情况符合需求预期

  • 测试报告: 同场景一,test01 重跑失败,运行结果全部被记录,而用例重跑,只希望记录最后的结果。

三、优化解决方案

以下方案解决重跑测试用例成功后后继测试用例无法继续运行的问题,并对测试报告进行优化。

3.1 TestListenerAdapter 方法重写

根据上面分析的 TestNG 逻辑,在对依赖测试用例的结果进行检查如果忽略重跑的中间结果只检查最后一次的运行结果,可以达到需求的。对于测试报告,同样的处理方式,忽略所有中间的测试用例运行结果,只记录最后结测试用例的中间运行结果为 Skipped,下面的代码通过重写 TestListenerAdapter 的 onTestSuccess()和 onTestFailure()方法,对测试用例的中间结果 skipped 进行了。代码如下:


public class ResultListener extends TestListenerAdapter {    @Override    public void onTestFailure(ITestResult tr) {        if(tr.getMethod().getCurrentInvocationCount()==1)        {            super.onTestFailure(tr);            return;        }
processSkipResult(tr); super.onTestFailure(tr); } @Override public void onTestSuccess(ITestResult tr) { if(tr.getMethod().getCurrentInvocationCount()==1) { super.onTestSuccess(tr); return; } processSkipResult(tr); super.onTestSuccess(tr); } // Remove all the dup Skipped results public void processSkipResult(ITestResult tr) { ITestContext iTestContext = tr.getTestContext(); Iterator<ITestResult> processResults = iTestContext.getSkippedTests().getAllResults().iterator(); while (processResults.hasNext()) { ITestResult skippedTest = (ITestResult) processResults.next(); if (skippedTest.getMethod().getMethodName().equalsIgnoreCase(tr.getMethod().getMethodName()) ) { processResults.remove(); } } }}
复制代码

3.2 配置结果处理 Listener 类

在配置文件进行全局设置或者在测试类中标记。


  • 方法一:在 TestNG 的配置 XML 中进行以下配置

  • 方法二:在测试类中通过 @Listeners 配置

3.3 场景一

1、 结果验证



2、结果分析


测试用例运行次数运行结果测试报告
Test012第一次:skipped;第二次:passed只在Passed的统计数量中test01被记录一次
Test021Passed记录一次passed

3.4 场景二

1、结果验证



2、结果分析


测试用例运行次数运行结果测试报告
Test013第一次:skipped;第二次:skipped;第三次:failedtest01只在failed统计中被记录一次
Test021Skipped依赖用例执行失败,test02结果为Skipped,只记录一次结果Skipped


本文转载自公众号宜信技术学院(ID:CE_TECH)。


原文链接


https://mp.weixin.qq.com/s/PLF-1RXbMPU1mWpOwiSamA


2020-05-26 10:002001

评论

发布
暂无评论
发现更多内容

Svelte 最新中文文档翻译(5)—— 基础标记

冴羽

JavaScript vue.js 前端 Svelte SvelteKit

AI 语音独角兽 ElevenLabs C 轮融资估值超 30 亿美元;港科大 Llasa TTS:15 秒声音克隆支持中英双语

声网

龙蜥衍生版 KOS 助力厦门高校创新实验室智算 300 节点成功迁移 | 龙蜥案例

OpenAnolis小助手

操作系统 龙蜥社区 龙蜥操作系统 龙蜥案例 Anolis OS

参与有奖 服务器操作系统用户调研问卷(2024年度)

OpenAnolis小助手

操作系统 龙蜥社区

iNet Network Scanner:Mac用户的网络监控与管理利器!

Rose

TinkerTool System 9:Mac系统优化与维护的全能助手!

Rose

高性能网络SIG双月度动态: 三年磨一剑,virtio-net AF_XDP 完成 Linux 主线零拷贝支持

OpenAnolis小助手

操作系统 龙蜥社区 龙蜥SIG月报

喜讯!龙蜥操作系统荣获 CSDN 2024 中国开发者影响力年度评选大奖

OpenAnolis小助手

操作系统 龙蜥操作系统 Anolis OS OS Copilot

回顾与展望,SOMA年终工作会议暨Meet Up圆满举办

OpenAnolis小助手

操作系统 龙蜥社区系统运维联盟

更安全、更丰富 、更兼容 Anolis OS 23.2 版本重磅上线

OpenAnolis小助手

开源 操作系统 龙蜥社区 Anolis OS Anolis OS 23.2 版本

📧Univer Go :电子表格结合AI,信息提取发邮件一键即达

梦数技术团队

Python JavaScript 自动化 电子表格 AI API

Go 语言高性能最佳实践

FunTester

AI英语考试APP的测试

北京木奇移动技术有限公司

软件外包公司 AI口语练习 AI英语学习

科研必备!GraphPad Prism 10数据分析与可视化的全新飞跃!

Rose

和鲸Heywhale荣获知名出版社 “2024 年度优秀合作伙伴”奖,共筑科技知识传播新未来

ModelWhale

出版社 图书出版

Coolbpf最新特性解读:profiler功能上线,助力性能分析和优化

OpenAnolis小助手

操作系统 ebpf 龙蜥技术 coolbpf 龙蜥系统运维联盟

对话式 AI 硬件开发者都关心什么?低延迟语音、视觉理解、Always-on、端侧智能、低功耗……丨 RTE Meetup 回顾

声网

“破冰”探索两周年,AI和媒体碰撞出了什么火花?

Alter

AI英语考试APP开发的技术难点

北京木奇移动技术有限公司

软件外包公司 AI口语练习 AI英语学习

逆向购物新浪潮?揭秘反向海淘与入局指南

代码忍者

反向海淘系统搭建

JustStream PRO for Mac:一键投屏,尽享大屏影音盛宴!

Rose

龙蜥开发者说:我与龙蜥社区相遇相惜的这些年 | 第 29 期

OpenAnolis小助手

操作系统 龙蜥开发者说

龙蜥社区加入智算产业联盟,助力构建开放、包容、普惠的 AI 新生态

OpenAnolis小助手

操作系统 龙蜥社区 智算产业联盟

龙蜥社区落地开源生态发展合作倡议新进展,推出内核 kABI 和配置统一规范

OpenAnolis小助手

开源 操作系统 龙蜥社区

什么是 Python 包管理器

克莱因瓶

好用的macOS壁纸软件Dynamic Wallpaper 臻选4K高清动态壁纸

Rose

Svelte 最新中文文档翻译(6)—— if、each、key、await 逻辑区块

冴羽

vue.js 前端 web前端 Svelte SvelteKit

总结与展望,龙蜥社区第 30 次运营委员会会议线上召开

OpenAnolis小助手

操作系统 龙蜥运营委员会会议

Elmedia Player Pro:MacOS上的全能音视频播放器!

Rose

Cloud Kernel SIG 月度动态:ANCK 新增支持多家厂商新硬件特性、发布多个小版本

OpenAnolis小助手

操作系统 龙蜥社区 龙蜥SIG月报

PIRF:422 Language Goofs – Egg Corns

Echo!!!

English

TestNG测试用例重跑详解及实践优化_软件工程_耿燕飞_InfoQ精选文章