您的位置:首页 > 其它

修改testNG源码,实现失败用例自动再执行

2015-05-18 10:09 274 查看

针对情况:

WebUI自动化测试中,网络不稳定,测试环境重启等难以控制,难以重现因素造成的用例失败会给用例用户造成不必要的困扰。

用例运行失败了,是发现bug了呢?还是运行不稳定?这往往须要耗费时间进行人工验证。若是运行不稳定造成的假警报,既要煞费苦心去修改用例以增强稳定性,同时也降低了大家对于自动化可靠性的信心。
解决方案:

通过改写testNG源代码,实现<test>级别的失败用例自动再执行:失败用例会重跑N次,直至成功
or 耗尽重试次数,testNG的结果报表中只会体现最后一次执行的结果。打个比方,用例A第一次执行失败了,立刻再重跑,再失败,立刻再重跑,成功了,那么,最后我们在testNG报表里面看到的就是最后那一次的运行数据,之前两次被完全过滤掉,只有在Log中才可以看到它们的痕迹。
之所以选择在<test>级别实现重跑失败用例,是因为testNG中,<test>是最小的独立单元,互相之间不存在依赖性。

方案优点:

写用例时只须要考虑用例能否跑通,不须考虑运行稳定性,稳定性由testNG包办;

跑用例时可以干掉网络不稳定造成的失败,如果测试环境重启速度够快的话,也可以干掉环境重启造成的失败。

适用于线上监控跑用例:一个用例只有连续N次失败才会报警。

具体实现过程:

1.checkout testNG代码:http://testng.googlecode.com/svn/trunk

2.修改如下几处代码:

2.1 SuiteRunner.java,在这里实现重试机制:每个<test>在被执行前都会进行备份,一旦执行失败了,备份立马再跑。

/** ChenKan 2012-05-12
Modified **/

private
void runTest(TestRunner tr) {

// tr.run();

// ISuiteResult
sr
= new SuiteResult(m_suite, tr);

// m_suiteResults.put(tr.getName(),
sr);

int reruntimes =
m_suite.getReruntimes().intValue();

if (reruntimes < 0) {

return;
}

TestRunner newtr = copyTest(tr);
newtr.run();

while ((reruntimes != 0) && ((newtr.getSkippedConfigurations().size() != 0) || (newtr.getSkippedTests().size()
!= 0) || (newtr.getFailedConfigurations().size() != 0) || (newtr.getFailedTests().size() != 0))) {
newtr = copyTest(tr);
newtr.run();
reruntimes--;
}

m_testRunners.set(m_testRunners.indexOf(tr), newtr);

ISuiteResult sr = new
SuiteResult(m_suite, newtr);

m_suiteResults.put(newtr.getName(), sr);
}

/** ChenKan 2012-05-12
added **/

private
TestRunner copyTest(TestRunner targettr) {

String name = targettr.getName();

for (XmlTest test :
m_suite.getTests()) {

if (test.getName().equalsIgnoreCase(name)) {

TestRunner tr = m_runnerFactory.newTestRunner(this, test,
m_invokedMethodListeners);

if (m_methodInterceptor !=
null) {
tr.setMethodInterceptor(m_methodInterceptor);
}
tr.addListener(m_textReporter);
System.out.println("copyTest
" + name);

return tr;
}
}

return
null;
}

2.2 实现从xml文件读取重试次数,这里须要修改2个类,基本是照样画葫芦:TestNGContentHandler.java

// ChenKan added on 2012-04-06
String reruntimes =
attributes.getValue("reruntimes");

if (null
!= reruntimes) {

m_currentSuite.setReruntimes(new Integer(reruntimes));
}

XmlSuite.java

// ChenKan added on 2012-04-06

public
static Integer
DEFAULT_RERUNTIMES = 0;

private Integer
m_reruntimes =
null;

public Integer getReruntimes() {

return
m_reruntimes !=
null ?
m_reruntimes :
DEFAULT_RERUNTIMES;
}

public
void setReruntimes(Integer reruntimes) {

m_reruntimes = reruntimes;
}

3.进入testNG源代码根目录,ant一下构建取得架包(须事先把ivy架包放到ant/lib文件夹中)

4.checkout Selenium源代码:http://selenium.googlecode.com/svn/tags/selenium-2.20.0

一开始使用的是Trunk代码,有Bug,Firefoxdriver关闭时会抛异常,然后,选择了2.20.0代码。

5.进入third_party/java/testng文件夹,使用之前构建testNG架包替换Selenium源码中testNG架包

6.在Selenium源码根目录,执行:go.bat
selenium-server-standalone


7.在build\java\server\src\org\openqa\grid\selenium目录下可以找到构建架包

8.改写testNG使用的xml文件中加入“reruntimes”属性

<suite reruntimes="3"
thread-count="1"
verbose="10"
name="相册UI自动化用例"
annotations="JDK"
time-out="600000">

收工!

9.之所以要把Selenium也重新打包,是因为Selenium内嵌了testNG,当ANT同时加载Selenium和testNG的jar包时,有可能加载的是Selenium里面内嵌的testNG!

使用实效:

自从使用了这一功能后,神马用例运行不稳定都成了历史垃圾:)

只要用例失败,几乎就是发现bug or
用例本身设计不合理,不会有假警报了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: