失败用例的重跑,实践

原创 2015年11月19日 15:08:01

1. 在Testng.xml配置文件,在Test标签下增加监听

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="TC_Operation_Suite" parallel="none" preserve-order="true">
<test name="swiftcoder2_0.TC_Operation">
   <groups>
       <run>

     <include name ="test.workflow" /> //执行初始条件
             <include name ="groupa" /> //执行组名为groupa的所有用例
       </run>
   </groups>
<classes>
   <class name = "swiftcoder2_0.TC_Operation" />//要哪个测试用例类,执行以上group
</classes>
<listeners>
   <!-- put the listener class here -->
<listener class-name = "swiftcoder2_0.RetryListener" /> //增加RetryListener的监听

<listener class-name = "swiftcoder2_0.TestngListener" />  //增加TestngListener的监听
   </listeners>
</test> <!-- Test -->

</suite> <!-- Suite -->

2.增加RetryListener类

package swiftcoder2_0;
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{
@Override
public void transform(ITestAnnotation annotation, 
Class testClass, Constructor testConstructor, Method testMethod) {
// TODO Auto-generated method stub
IRetryAnalyzer retry = annotation.getRetryAnalyzer();
if(retry == null){
annotation.setRetryAnalyzer(TestngRetry.class); //设置RetryAnalyzer
}
}

3. 增加TestngRetry类

package swiftcoder2_0;
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
import org.testng.log4testng.Logger;
import GL.GL;
public class TestngRetry implements IRetryAnalyzer{
private static Logger logger = Logger.getLogger(TestngRetry.class);
private int retryCount = 1;
private static int maxRetryCount;

@Override
public boolean retry(ITestResult result) {
//get the max retry count 
maxRetryCount = Integer.parseInt(GL.getString("maxRunCount")); //在config.properties文件中设置maxRunCount 值
// TODO Auto-generated method stub
if (retryCount <= maxRetryCount) {
String message = "running retry for  '" + result.getName() + "' on class " + this.getClass().getName() + " Retrying "
+ retryCount + " times";
logger.info(message);
retryCount++;
return true;
}

return false;
}

}


4. 增加TestngListener类

package swiftcoder2_0;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.testng.ITestContext;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
import org.testng.log4testng.Logger;
public class TestngListener extends TestListenerAdapter{
private static Logger logger = Logger.getLogger(TestngListener.class);
@Override
public void onTestFailure(ITestResult tr){
super.onTestFailure(tr);
logger.info(tr.getName() + " Failure");
}
@Override
public void onTestSkipped(ITestResult tr){
super.onTestSkipped(tr);
logger.info(tr.getName() + " Skipped");
}
@Override
public void onTestSuccess(ITestResult tr){
super.onTestSuccess(tr);
logger.info(tr.getName() + " Success");
}
@Override
public void onTestStart(ITestResult tr){
super.onTestStart(tr);
logger.info(tr.getName() + " Start");
}
@Override
public void onFinish(ITestContext testContext){
//super.onFinish(testContext);
Iterator<ITestResult> listOfFailedTests = testContext.getFailedTests().getAllResults().iterator();
while(listOfFailedTests.hasNext()){
ITestResult failedTest = listOfFailedTests.next();
ITestNGMethod method = failedTest.getMethod();
if(testContext.getFailedTests().getResults(method).size()>1){
listOfFailedTests.remove();
}else{
if(testContext.getPassedTests().getResults(method).size()>0){
listOfFailedTests.remove();
}
}
}

}

}

5. 设置config.properties文件

maxRunCount=3

6. TC_Operation用例文件

package swiftcoder2_0;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;


import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;


import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeMethod;


import org.testng.annotations.BeforeTest;
import org.testng.annotations.Configuration;
import org.testng.annotations.Test;
import swiftcoder2_0.MultiOutputStream;
import swiftcoder2_0.Swiftcoder2_0;
import GL.GL;
import GL.Logs;
import swiftcoder2_0.TestngRetry;
public class TC_Operation {
//@variables
int c =0;
int a =0;
@BeforeTest
@Configuration(beforeTestClass= true, groups = {"test.workflow"})
public void SetUp() throws InterruptedException, IOException{ 
System.out.println("----Before Test--------");

}

@AfterTest
@Configuration(afterTestClass= true, groups = {"test.workflow"})
public void TearDown(){
System.out.println("----After Test--------");
}

@BeforeMethod
@Configuration(beforeTestMethod= true, groups = {"test.workflow"})
public void BeforeMethod() throws InterruptedException{
System.out.println("----Before Method--------");

}
@AfterMethod
@Configuration(afterTestMethod= true, groups = {"test.workflow"})
public  void AfterMethod() throws InterruptedException{
//close the instance of the web driver
GL.quitWebDriver(wd);
System.out.println("----After Method--------");
}
@Test(groups = {"groupa"}, retryAnalyzer = TestngRetry.class)
public void testa(){
a++;
if(a <=2 ){
Assert.fail();
}
System.out.println("testa");
}

@Test(groups = {"groupa"} ,retryAnalyzer = TestngRetry.class
public void testc(){
c++;
if(c <=3){

Assert.fail();

}
System.out.println("testc");
}

@Test(groups = {"groupb"}, retryAnalyzer = TestngRetry.class)
public void testb(){
System.out.println("testb");

}
@Test(groups = {"groupb"}, retryAnalyzer = TestngRetry.class)
public void testb_1(){
System.out.println("testb");

}

}

逻辑分析:

从testng_groups.xml加载RetryListener+TestngListener,2个监听类,在运行每个case后,调用

TestngRetry类和从TestngListener类执行结果,接着 将此结果传入到TestngRetry的retry函数中,如果Fail,当前用例连续执行最大次数为maxRunCount,如果Pass,则不需Retry调用。最后在TestngListener运行结果中删除同一case id no. 的重复用例,对每个用例结果只保留最后运行结果。

7. 运行结果

7.1 如果xml文件不加入TestngListener监听

[TestNG] Running:
  E:\Documents\QA.Management\automation\swiftcoder2_0\testng-groups.xml

----Before Test--------
----Before Method--------
----After Method--------
----Before Method--------
----After Method--------
----Before Method--------
testa
----After Method--------
----Before Method--------
----After Method--------
----Before Method--------
----After Method--------
----Before Method--------
----After Method--------
----Before Method--------
testc
----After Method--------
----After Test--------


===============================================
TC_Operation_Suite
Total tests run: 7, Failures: 5, Skips: 0

7.2 如果xml文件加入TestngListener监听

[TestNG] Running:
  E:\Documents\QA.Management\automation\swiftcoder2_0\testng-groups.xml


This is log file
----Before Test--------
----Before Method--------
----After Method--------
----Before Method--------
----After Method--------
----Before Method--------
testa
----After Method--------
----Before Method--------
----After Method--------
----Before Method--------
----After Method--------
----Before Method--------
----After Method--------
----After Test--------


===============================================
TC_Operation_GroupsSuite
Total tests run: 2, Failures: 1, Skips: 0
===============================================


说明:若需要每个用例,需要监听,需要一一增加@Test(groups = {"groupb"},retryAnalyzer = TestngRetry.class)

如果测试时,用例Fail,最多执行maxRunCount次,用例Pass,无需重跑


xml文件加入TestngListener监听作用:首先解决TestNg生成的index.html文件中个数不对的问题,这个问题只需要在Testng监听器的onFinish方法中,等所有用例运行完之 后,检查用例,按照class+method+dataprodiver的名称生成hashcode获取唯一id,如果fail的用例中存在重复的则在 fail的用例中剔除掉。

参考资料:

http://testng.org/doc/documentation-main.html#test-groups 

TestNG的官网资料 listeners的知识

http://www.ibm.com/developerworks/cn/opensource/os-cn-testinglistener/index.html 
实战 TestNG 监听器
http://www.yeetrack.com/?p=1015
testng增加失败重跑机制
http://testng.org/javadoc/ 

JavaDoc API资料

https://martinholladay.wordpress.com/2013/11/16/testng-adjusting-test-counts-on-retry/

TESTNG & WEBDRIVER – ADJUSTING TEST COUNTS ON RETRY


版权声明:本文为博主原创文章,未经博主允许不得转载。

使用testng listener实现测试用例失败重跑功能

我们通过重写testng的retry方法和transform方法来实现用例失败重跑的功能。首先添加两个文件TestngRetry.javapublic class TestngRetry implem...
  • lala9517
  • lala9517
  • 2015年07月20日 12:26
  • 2379

如何解决testng执行用例失败自动重跑问题

今天给大家分享一下testng执行用例失败自动重跑问题的解决办法,为什么要写这篇博客?有人会说了,网上找一车一车的,干嘛自己搁这儿写这个。。。 没错,网上是有很多,只是我感觉按照网上的说法去做不一定一...
  • MenofGod
  • MenofGod
  • 2017年06月02日 17:56
  • 1923

JUnit结果重跑失败用例(支持Mvn和Ant)

1.背景之前一篇文章介绍过 JUnit4—实践三:支持多线程,失败重试执行测试case的方法, 是ant 执行用例结束后,根据输出日志(类似:TEST-com.weibo.cases.suite.H...
  • neven7
  • neven7
  • 2015年04月23日 16:02
  • 2281

结合testng实现用例失败重跑

我们在运行自动化测试用例的时候,经常会出现一些异常的情况的情况导致用例失败的问题。所以我们可能会希望对于失败的测试用例再重新运行一次,下来我们来看看结合testng如何使用这个功能 你需要在你的项目中...
  • qq744746842
  • qq744746842
  • 2016年05月16日 22:14
  • 3516

robotium 测试用例操作失败自动重跑测试用例方法

我们在做自动化的时候,偶尔会遇到测试用例莫名其妙的失败,再次运行又OK的情况。针对这种情况我们有必要在测试用例操作失败时自动重跑 来避免不必要的核查。 那么针对robotium框架该如何实现自动重跑测...
  • w306695293
  • w306695293
  • 2017年02月10日 14:05
  • 542

python的unittest框架用例失败重运行解决方法

当我们在做自动化测试的时候,发现unittest不能支持用例失败自动重运行机制,需要做扩展,达到像java的testng一样支持失败重运行,提高测试质量。 第一个解决方法是,我们使用decorator...
  • hqzxsc2006
  • hqzxsc2006
  • 2015年12月18日 10:19
  • 3864

解决RobotFramework用例执行失败自动重跑问题

使用自动化脚本进行测试,经常受环境影响等各方面导致本能成功的脚本失败,下面介绍了RFS框架下,失败重跑的方法: 通过改写RobotFramework源代码增加--retry选项,实现test级别的失败...
  • MenofGod
  • MenofGod
  • 2017年03月06日 11:49
  • 1496

TestNG实现用例运行失败自动截图和重跑

在前面我的自动化测试框架系列文章中,有一个知识点没有讲到,现在补上。 在运行自动测试脚本时,经常会需要增加失败时自动截图的功能,以及失败重跑功能,下面介绍一下通过监听器的方式来实现自动截图和重跑功能...
  • ToBeTheEnder
  • ToBeTheEnder
  • 2016年09月27日 20:58
  • 5349

Python+unittest用例失败时候,自动重跑

一.参考了一下别人优化内容,再自己优化了一下。可以达到用例失败时候,能够自动重跑   1.下载suilt.py,替换unittest下面的脚本suilt.py。   2.在每个主脚本后面添加一个方法:...
  • a_1060584570
  • a_1060584570
  • 2017年12月16日 18:09
  • 174

Robot Framework-失败用例自动重跑

使用自动化脚本进行测试,经常受环境影响等各方面导致本能成功的脚本失败,下面介绍了RFS框架下,失败重跑的方法: 通过改写RobotFramework源代码增加–retry选项,实现test级别的失败用...
  • weixin_36650524
  • weixin_36650524
  • 2017年12月12日 10:30
  • 40
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:失败用例的重跑,实践
举报原因:
原因补充:

(最多只允许输入30个字)