Testng 的重试机制 在不写代码的情况没有提供可配置方式,需要自己实现其提供的接口,并以监听器的方式提供出来才可使用,具体步骤如下:
1.首先需要实现 IRetryAnalyzer接口
package ec.qa.autotest.ui.testng.listener; import org.testng.IRetryAnalyzer; import org.testng.ITestResult; import org.testng.Reporter; import ec.qa.autotest.ui.constants.CommonConstants; import ec.qa.autotest.ui.testbase.TestBase; /** * @author xin.wang *实现testng接口实现用例失败重跑 */ public class RetryToRunCase implements IRetryAnalyzer{ private int retryCount = 1; private static int maxRetryCount; public int getRetryCount() { return retryCount; } public static int getMaxRetryCount() { return maxRetryCount; } @SuppressWarnings("static-access") public RetryToRunCase(){ this.maxRetryCount = CommonConstants.RETRY_COUNT; } public boolean retry(ITestResult result) { if (retryCount <= maxRetryCount) { Reporter.setCurrentTestResult(result); TestBase.success = false; retryCount++; return true; } return false; } }
2.需要实现testNg监听器的2个接口,onFinish()方法的代码是为了在测试结果报告中剔除掉失败后重试成功的结果.
package ec.qa.autotest.ui.testng.listener; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.testng.IAnnotationTransformer; import org.testng.IRetryAnalyzer; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestResult; import org.testng.annotations.ITestAnnotation; /** * @author xin.wang * 用例失败重跑的监听器 */ public class TestngRetryListener implements IAnnotationTransformer,ITestListener { @SuppressWarnings("rawtypes") public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { IRetryAnalyzer retry = annotation.getRetryAnalyzer(); if (retry == null) { annotation.setRetryAnalyzer(RetryToRunCase.class); } } public void onFinish(ITestContext testContext) { ArrayList<ITestResult> testsToBeRemoved = new ArrayList<ITestResult>(); Set<Integer> passedTestIds = new HashSet<Integer>(); for (ITestResult passedTest : testContext.getPassedTests().getAllResults()) { passedTestIds.add(getId(passedTest)); } Set<Integer> failedTestIds = new HashSet<Integer>(); for (ITestResult failedTest : testContext.getFailedTests().getAllResults()) { int failedTestId = getId(failedTest); if (failedTestIds.contains(failedTestId) || passedTestIds.contains(failedTestId)) { testsToBeRemoved.add(failedTest); } else { failedTestIds.add(failedTestId); } } for (Iterator<ITestResult> iterator = testContext.getFailedTests().getAllResults().iterator(); iterator .hasNext();) { ITestResult testResult = iterator.next(); if (testsToBeRemoved.contains(testResult)) { iterator.remove(); } } } private int getId(ITestResult result) { int id = result.getTestClass().getName().hashCode(); id = id + result.getMethod().getMethodName().hashCode(); id = id + (result.getParameters() != null ? Arrays.hashCode(result.getParameters()) : 0); return id; } public void onTestFailure(ITestResult result) { } public void onTestStart(ITestResult result) { // TODO Auto-generated method stub } public void onTestSuccess(ITestResult result) { // TODO Auto-generated method stub } public void onTestSkipped(ITestResult result) { // TODO Auto-generated method stub } public void onTestFailedButWithinSuccessPercentage(ITestResult result) { // TODO Auto-generated method stub } public void onStart(ITestContext context) { // TODO Auto-generated method stub } }
添加testng监听器的方法很多如下 个人习惯 命令行方式和基于testng的XML文件配置方式:
前文已讲过,监听器的编码过程就是定义一个 Java 类实现监听器接口。下面简单介绍一下监听器的几种使用方法。
TestNG 通过 testng.xml 配置所有的测试方法。Testng.xml 提供了 listeners 和 listener 标签用来添加自定义的监听器。下面示范的是本文示例代码中包含的 testng.xml 文件。
<suite name="TestNGSample"> <listeners> <listener class-name="listeners.OSFilter" /> <listener class-name="listeners.ProgressTracker" /> </listeners> <test name="ProgressTracker Demo"> <classes> <class name="tests.SampleTest" /> </classes> </test> </suite>
通过 @Listeners 注释,可以直接在 Java 源代码中添加 TestNG 监听器。下面示范的是本文示例代码中如何使用 @Listeners 注释。
@Listeners({ OSFilter.class, ProgressTracker.class }) public class SampleTest { @Test(groups = { OSNames.OS_LINUX }) public void test1() { sleep(5000); System.out.println(">>>test1"); }
值得注意的是:
Java SE 6 开始提供了 ServiceLoader。它可以帮助用户查找、加载和使用服务提供程序,从而在无需修改原有代码的情况下轻易地扩展目标应用程序。通过 ServiceLoader 的方式使用 TestNG 监听器,简单来说,就是创建一个 jar 文件,里面包含 TestNG 监听器的实现类已经 ServiceLoader 需要的配置信息,并在运行 TestNG 时把该 jar 文件加载到类路径中。具体步骤请查阅 TestNG 官方文档。这样做的好处是:
通过命令行使用 TestNG 监听器,需要在命令行中加入”-listener”参数。如要指定多个监听器,用逗号分隔。下面是一个调用的示例。
java org.testng.TestNG -listener MyListener testng1.xml [testng2.xml testng3.xml ...]
TestNG 在多种 IDE 中都有插件支持,比如 Eclipse 和 IDEA。因为最终 IDE 也是以命令行的方式调用 TestNG,因此在 IDE 中也是通过添加“-listener”参数使用 TestNG 监听器。下图以 Eclipse 为例示范了 TestNG 监听器的配置方法。