概述:在自动化案例运行中,受到外部影响,比如网络不稳定,有些页面刷新较慢等因素导致案例执行失败,这时就需要知道testNg失败重试的机制
本篇文章主要从局部和全局两种失败案例重试两个方面讲解:
一、局部
步骤:
1.新建一个类FaileRetry实现IRetryAnalyzer接口,重写retry方法
public class FaileRetry implements IRetryAnalyzer{
public static Logger log = Logger.getLogger(FaileRetry.class);
private int currentCount = 1;//当前正在运行的次数 局部
private static int maxRetryCount = 2;//允许重试的最大次数
@Override
public boolean retry(ITestResult result) {
if(currentCount <= maxRetryCount){
log.info(“当前测试方法【” + result.getMethod() +"】执行失败,进入失败案例重试模式,正在进行【"+currentCount+"】次重试");
currentCount ++;
return true;
}
int index = currentCount - 1;
log.info(“当前案例已经运行【”+index +"】次,不再进行失败重试,如果有多条案例,继续执行下条案例");
return false;
}
2.新建一个测试类,在测试方法中加上 @Test(retryAnalyzer = FaileRetry.class)注解
public class Test3{
@Test(retryAnalyzer = FaileRetry.class)
public static void success(){
System.out.println(“这是 success 方法”);
Assert.assertEquals(false, true);
}
}
二、全局
1.跟局部一样先新建一个类FaileRetry实现IRetryAnalyzer接口,重写retry方法,区别是当前正在运行的次数的变量要是公共静态的共享变量
public class FaileRetry implements IRetryAnalyzer{
public static Logger log = Logger.getLogger(FaileRetry.class);
public static int currentCount = 1;//当前正在运行的次数 全部
private static int maxRetryCount = 2;//允许重试的最大次数
@Override
public boolean retry(ITestResult result) {
if(currentCount <= maxRetryCount){
log.info(“当前测试方法【” + result.getMethod() +"】执行失败,进入失败案例重试模式,正在进行【"+currentCount+"】次重试");
currentCount ++;
return true;
}
int index = currentCount - 1;
log.info(“当前案例已经运行【”+index +"】次,不再进行失败重试,如果有多条案例,继续执行下条案例");
return false;
}
2.新建一个类RetryListener实现IAnnotationTransformer接口,重写transform方法,该类的作用是用来监听所有的测试方法是否有retryAnalyzer注解属性,如果有该属性则不会执行我们设定的重跑机制(局部重跑的优先级比全局的高)
public class RetryListener implements IAnnotationTransformer{
@Override
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
IRetryAnalyzer retryAnalyzer = annotation.getRetryAnalyzer();
if(retryAnalyzer ==null ){//说明测试方法中未设置注解属性retryAnalyzer
annotation.setRetryAnalyzer(FaileRetry.class);
}
}
}
3.第一条案例失败重试次数到达最大值时,后面的案例则永远不会进入重跑机制,所以在每条案例重跑完后,需要重置当前正在运行的次数为初始值
新建一个类CustomListener继承TestListenerAdapter类,重写onTestFailure和onTestSuccess方法
public class CustomListener extends TestListenerAdapter{
public static Logger logger = Logger.getLogger(CustomListener.class);
//监听测试方法(1个Test为一个测试方法)
@Override
public void onTestFailure(ITestResult tr) {
super.onTestFailure(tr);// 如果测试用例执行完所有重试以后依然失败的话,重新设置currentCount为初始值,方便其他用例执行重试
logger.info(“用例执行失败,重试机制的次数恢复初始值”);
FaileRetry.currentCount = 1;
}
@Override
public void onTestSuccess(ITestResult tr) {
// 如果测试用例执行重试的时候,执行成功了,也需要设置currentCount为初始值,方便其他用例执行重试
logger.info(“用例执行成功,重试机制的次数恢复初始值”);
FaileRetry.currentCount = 1;
super.onTestSuccess(tr);
}
}
4.有了重试以后,发现重试执行的用例,全部记录到跳过(skipped)里面了,这样会影响我们的测试总数,测试结束后把重试的用例结果从skipped中去掉
新建一个类TestListener 实现IResultListener接口,重写onFinish方法(局部重试也用次方法)
public class TestListener implements IResultListener{
@Override
public void onFinish(ITestContext context) {
Iterator listOfSkippedTests = context.getSkippedTests().getAllResults().iterator();
while(listOfSkippedTests.hasNext()){
ITestResult SkippedTest = listOfSkippedTests.next();
ITestNGMethod method = SkippedTest.getMethod();
if(context.getSkippedTests().getResults(method).size() >0){
listOfSkippedTests.remove();
}else{
if(context.getPassedTests().getResults(method).size() > 0){
listOfSkippedTests.remove();
}
}
}
}
5.将监听类添加到testng.xml文件中
<suite name="Suite" parallel="tests" thread-count="1">
<test name="device1">
<classes>
<class name="retry2.Test1" />
<class name="retry2.Test2" />
</classes>
</test>
<listeners>
<listener class-name="retry2.RetryListener" />
<listener class-name="retry2.CustomListener" />
<listener class-name="retry2.TestListener" />
</listeners>
</suite>
总结:
注意点:testng版本尽量用高版本,不然可能会出现死循环等其他问题,我用6.14.3版本。
TestNG提供了多种监听器:AnnotationTransformer,IAnnotationTransformer2,IConfigurable,
IConfigurationListener,IConfigurationListener2,IExecutionListener,IHookable,
IInvokedMethodListener,IInvokedMethodListener2,IMethodInterceptor,IReporter,
ISuiteListener,ITestListener(TestListenerAdapter 已经实现 ITestListener)