testNG retry 失败的testcase只需要在xml中配置一个listener即可
问题情况
先说下问题情况,最近在做testNG与selenium集成做自动化测试的问题。
因为如果将testNG做UI 测试的话,很多情况下可能测试是失败的,但是这些失败可能是一些其他的问题导致的,可能是脚本的问题或者是网络环境不稳定导致的,所以我们需要重新尝试运行这个失败的测试用例。
testNG倒是没有直接的retry testcase的功能,不过它却提供了很多的接口,我们可以实现这些接口来得到retry的效果。
在google上看到淘宝的QA项目组采用Ruby语言将testNG的源代码修改了retry的功能,然后又重新build后这样做的。这是一个solution,但是我不推荐。原因有两个:
1,修改的jar包是针对指定的testNG版本的,所以如果我们需要体验testNG的新版本功能,这个jar可能就需要在源码基本上重新build有点 不太合适,详细地址是:https://github.com/NetEase/Dagger/wiki/Retry-Failed-Or-Skipped-Testcases
2,该种修改的方法只能使用在testcase级别上,如果需要针对所有的testNG的testsuite都是用这种特性,可能就需要每个testcase都表明他们是使用这个retry功能,有点代码亢余。像这样在testcase中声明retry的类:
import org.apache.log4j.Logger;
import org.testng.Assert;
import org.testng.annotations.Test; import com.hp.baserunner.RetryFail;
import com.hp.pop.DemoPage; public class DemoRun { private static Logger log=Logger.getLogger(DemoRun.class);
@Test(retryAnalyzer=RetryFail.class)// 这里声明retry的类,可以看到如果这样每个testcase可能都需要这样做,代码是不是有点多啊 :(
public void demoTest()
{
DemoPage dp=new DemoPage();
dp.demoTest();
}
@Test
public void demoTest2()
{
DemoPage dp2=new DemoPage();
dp2.demoTest2();
}
}
既然是框架这样写肯定就有点不太合适了。
框架设计使用
testNG中的对应的提供这些功能的接口有这些:
Interface IRetryAnalyzer 这个就是retrytestcase的一个接口,然后impletment这个接口后实现相应的方法即可:
有一个类 RetryAnalyzerCount 已经实现了以上的这个接口的方法:
package org.testng.util; import org.testng.IRetryAnalyzer;
import org.testng.ITestResult; import java.util.concurrent.atomic.AtomicInteger; /**
* An implementation of IRetryAnalyzer that allows you to specify
* the maximum number of times you want your test to be retried.
*
* @author tocman@gmail.com (Jeremie Lenfant-Engelmann)
*/
public abstract class RetryAnalyzerCount implements IRetryAnalyzer { // Default retry once.
AtomicInteger count = new AtomicInteger(1); /**
* Set the max number of time the method needs to be retried.
* @param count
*/
protected void setCount(int count) {
this.count.set(count);
} /**
* Retries the test if count is not 0.
* @param result The result of the test.
*/
@Override
public boolean retry(ITestResult result) {
boolean retry = false; if (count.intValue() > 0) {
retry = retryMethod(result);
count.decrementAndGet();
}
return retry;
} /**
* The method implemented by the class that test if the test
* must be retried or not.
* @param result The result of the test.
* @return true if the test must be retried, false otherwise.
*/
public abstract boolean retryMethod(ITestResult result);
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
所以从上面可以看出,如果直接使用继承这个RetryAnalyzerCount 类还是省不少事,直接就可以使用了。
Class TestListenerAdapter
IConfigurationListener, IConfigurationListener2, org.testng.internal.IResultListener, org.testng.internal.IResultListener2, ITestListener, ITestNGListener
上面的是另一个类实现了retry的操作的类。这里不使用。
我们今天所使用的是IRetryAnalyzer 接口的,代码如下:
package com.com.baserunner;
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
/**
* @author sumeetmisri@gmail.com
* @modify alterhu2020@gmail.com
* @version 1.0
* @category
*
*/ public class RetryFail implements IRetryAnalyzer
{
private final int m_maxRetries = 1;
private final int m_sleepBetweenRetries = 1000;
private int currentTry;
private String previousTest = null;
private String currentTest = null;
public RetryFail()
{
currentTry = 0;
} @Override
public boolean retry(final ITestResult result)
{
// If a testcase has succeeded, this function is not called.
boolean retValue = false; // Getting the max retries from suite.
// String maxRetriesStr = result.getTestContext().getCurrentXmlTest().getParameter("maxRetries");
String maxRetriesStr = result.getTestContext().getSuite().getParameter("maxRetries");
int maxRetries = m_maxRetries;
if(maxRetriesStr != null)
{
try
{
maxRetries = Integer.parseInt(maxRetriesStr);
}
catch (final NumberFormatException e)
{
System.out.println("NumberFormatException while parsing maxRetries from suite file." + e);
}
} // Getting the sleep between retries from suite.you can from the suite parameter
String sleepBetweenRetriesStr = result.getTestContext().getSuite().getParameter("sleepBetweenRetries");
int sleepBetweenRetries = m_sleepBetweenRetries;
if(sleepBetweenRetriesStr != null)
{
try
{
sleepBetweenRetries = Integer.parseInt(sleepBetweenRetriesStr);
}
catch (final NumberFormatException e)
{
System.out.println("NumberFormatException while parsing sleepBetweenRetries from suite file." + e);
}
} currentTest = result.getTestContext().getCurrentXmlTest().getName(); if (previousTest == null)
{
previousTest = currentTest;
}
if(!(previousTest.equals(currentTest)))
{
currentTry = 0;
} if (currentTry < maxRetries &&!result.isSuccess())
{
try
{
Thread.sleep(sleepBetweenRetries);
}
catch (final InterruptedException e)
{
e.printStackTrace();
}
currentTry++;
result.setStatus(ITestResult.SUCCESS_PERCENTAGE_FAILURE);
retValue = true; }
else
{
currentTry = 0;
}
previousTest = currentTest;
// if this method returns true, it will rerun the test once again. return retValue;
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }还有一个lisetner需要加入到testNG的配置文件中:
package com.coma.baserunner; import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import org.testng.IAnnotationTransformer;
import org.testng.IRetryAnalyzer;
import org.testng.annotations.ITestAnnotation; public class RetryListener implements IAnnotationTransformer { @SuppressWarnings("rawtypes")
@Override
public void transform(ITestAnnotation annotation, Class testClass,
Constructor testConstructor, Method testMethod) { IRetryAnalyzer retry = annotation.getRetryAnalyzer();
if (retry == null) {
//annotation.setRetryAnalyzer(RetryAnalyzer.class);
annotation.setRetryAnalyzer(RetryFail.class);
}
} }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }然后在testNG的xml的配置文件中如下配置即可:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="FirstSuite" parallel="false" >
<!-- <parameter name="configfile" value="/resources/config.properties"></parameter> -->
<parameter name="excelpath" value="resources/TestData.xls"></parameter>
<listeners>
<listener class-name="com.com.baserunner.RetryListener"></listener>
</listeners>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
以上的配置方法没有任何问题,唯一的缺陷是,运行的时候testNG的报告中会将retry的testcase的次数也计算在内,所以可能造成,运行后的testcase数目不准确,关于这个问题网上也有人在讨论,可是一直都没有得到一个好的接解决。
最近觉得仔细看看testNG的源代码,看看能不能修改下对应的testNG的报告。使得结果显示的testcase数据与实际的一致,retry的testcase只计算最后一次运行成功的。
如果有结果,再更新。。。。。。。
testNG retry 失败的testcase只需要在xml中配置一个listener即可的更多相关文章
- Java 在pom.xml中配置build resources, 来防止我们资源导出失败问题(Maven项目)
在pom.xml中配置build, 来防止我们资源导出失败问题 <!--在build中配置resources, 来防止我们资源导出失败问题--> <build> <res ...
- 如何只克隆git仓库中的一个分支?
git clone -b 例如: git clone -b 指定的分支名字
- 思路:当一个表嵌套另一个表时候 只需在dao中引入该mapper即可 进行正常的数据插入 查询 修改等
- 解决在web.xml中配置server服务器启动失败问题
一.问题"Server Tomacat v8.5 Server at locallhost failed to start" 二.解决方法:删除注释@webServlet 三.分析 ...
- testng跑失败用例重试
testng 提高用例通过率,失败用例要重新运行一次 步骤: 1.新建一个Retry 类,implements IRetryAnalyzer接口,这个类里面确定重跑次数,以及分析每次失败是否需要重新运 ...
- testng增加失败重跑机制
注: 以下内容引自 http://www.yeetrack.com/?p=1015 testng增加失败重跑机制 Posted on 2014 年 10 月 31 日 使用Testng框架搭建自动测试 ...
- (转)testng对失败时截图处理
写这篇微博之前,自动化测试代码中有对于失败测试截图的功能,但是却散落在各个catch语句块中.不便于以后的扩展和维护,AOP思想里说明是面向切面编程,把公共的组件提取出来,可以单独修改维护. 但是直到 ...
- AGS中通过FeatureServer插入数据失败、插入数据在WMTS请求中无法显示以及version概念的讨论
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 在多个项目中,当我方接口给其他部门人员使用时出现了插入数据失 ...
- SQL Server 2008 R2中配置作业失败后邮件发送通知
SQL Server日常维护中难免会遇到作业失败的情况.失败后自然需要知道它失败了,除了例行检查可以发现出错以外,有一个较实时的监控还是很有必要的.比较专业的监控系统比如SCOM虽然可以监控作业执行情 ...
随机推荐
- C# ApartmentState 枚举,指定线程单元状态
1.ApartmentState 指定的单元状态 Thread. 命名空间: System.Threading程序集: mscorlib(位于 mscorlib.dll) 成员 成员 ...
- mac或者linux磁力下载方法:远离渣雷
wget是linux下常用的命令行下载工具,是Linux用户是必不可少的工具,尤其对于网络管理员,经常要下载一些软件. t-get是一个简单的命令行BT下载工具,可以用于BT种子和磁力链接的下载 tg ...
- @Autowired注解和静态方法 NoClassDefFoundError could not initialize class 静态类
NoClassDefFoundError could not initialize class 静态类 spring boot 静态类 java.lang.ExceptionInInitializer ...
- anaconda里面安装tensorflow
这篇文章讲的比较好: https://blog.csdn.net/evaljy/article/details/70209957 用这篇文章的内容,能够安装成功
- Unique Binary Search Trees II leetcode java
题目: Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. F ...
- vue-自定义组件传值
项目中,我们经常会遇到自定义组件传值的问题,方法很多种,但是原理很简单,下述文档总结实际项目中使用的传值方式. 父组件传递给子组件某一值,子组件内会修改该值,然后父组件需要获取新值 在 Vue 中 ...
- SQL Server 2005 Integration Services (SSIS)数据源之MySQL
一安装MySQL数据库的ODBC驱动 下载MySQL Connector ODBC 3.51.rar 单击setup按默认安装即可! 如下图所示,在ODBC数据源管理器中看到“MySQL ODBC 3 ...
- mybatis @Select注解中如何拼写动态sql
@Mapper public interface DemandCommentMapper extends BaseMapper<DemandComment>{ @Select(" ...
- IIS 7.5: HOW TO ENABLE TLS 1.1 AND TLS 1.2
In IIS 7.5, which is installed on Windows 2008 R2 servers, only SSL 3.0 and TLS 1.0 are enabled for ...
- This is a bug I believe, and it took me 2-3 days to figure it out. Please do the following to get it working,
This is a bug I believe, and it took me 2-3 days to figure it out. Please do the following to get it ...