通过测试监听器删除(复制)失败的TestNG结果
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过测试监听器删除(复制)失败的TestNG结果相关的知识,希望对你有一定的参考价值。
类似于此处发布的解决方案TestNG retrying failed tests doesn't output the correct test results,我试图在onFinish(ITestContext上下文)中使用测试侦听器删除(重复)测试结果。
尽管使用context.getFailedTests()。removeResult(result)删除结果似乎工作正常(结果实际上已被删除),但似乎存在“某些其他位置”,其中结果被拉出,因为构建仍然失败。
还要注意,当我从上面的文章(其中有一个重复的失败被删除和一个通过测试)运行样本测试时,我得到了“测试结果”(没有按预期清理)与“套件结果”的区别(重复故障按预期删除)。
而且,报告从哪里提取结果以决定是否使构建失败?或者只是它在我清理失败的测试之前拉动结果......?
===============================================
Default test
Tests run: 3, Failures: 2, Skips: 0
===============================================
===============================================
Default suite
Total tests run: 2, Failures: 1, Skips: 0
===============================================
编辑:只是为了澄清,我们正在使用maven运行这些测试,他们是IT,因此我们使用failsafe插件运行它们。问题是即使看起来测试被删除,mvn验证仍然无法构建,因为它认为无论如何都会发现构建失败。
而且如果从Eclipse运行这样的测试,即使删除了测试,当套件完成时,仍会在日志中打印失败。
关于RetryAnalyzer:我根本不会考虑使用RetryAnalyzer良好/最佳实践,但如果您发现自己处于需要解决问题的情况,例如你继承了一个依赖RetryAnalyzer的测试套件,你可能会觉得这很有用。
尝试使用此代码:
ListenerApadter:
public class MyTestListenerAdapter extends TestListenerAdapter {
@Override
public void onTestFailure(ITestResult result) {
if (result.getMethod().getRetryAnalyzer() != null) {
MyRetryAnalyzer retryAnalyzer = (MyRetryAnalyzer)result.getMethod().getRetryAnalyzer();
if(retryAnalyzer.isRetryAvailable()) {
result.setStatus(ITestResult.SKIP);
} else {
result.setStatus(ITestResult.FAILURE);
}
Reporter.setCurrentTestResult(result);
}
}
@Overrride
public void onFinish(ITestContext context) {
Iterator<ITestResult> failedTestCases =context.getFailedTests().getAllResults().iterator();
while (failedTestCases.hasNext()) {
System.out.println("failedTestCases");
ITestResult failedTestCase = failedTestCases.next();
ITestNGMethod method = failedTestCase.getMethod();
if (context.getFailedTests().getResults(method).size() > 1) {
System.out.println("failed test case remove as dup:" + failedTestCase.getTestClass().toString());
failedTestCases.remove();
} else {
if (context.getPassedTests().getResults(method).size() > 0) {
System.out.println("failed test case remove as pass retry:" + failedTestCase.getTestClass().toString());
failedTestCases.remove();
}
}
}
}
}
RetryAnalizer:
public class MyRetryAnalyzer implements IRetryAnalyzer {
private static int MAX_RETRY_COUNT = 3;
AtomicInteger count = new AtomicInteger(MAX_RETRY_COUNT);
public boolean isRetryAvailable() {
return (count.intValue() > 0);
}
@Override
public boolean retry(ITestResult result) {
boolean retry = false;
if (isRetryAvailable()) {
System.out.println("Going to retry test case: " + result.getMethod() + ", " + (MAX_RETRY_COUNT - count.intValue() + 1) + " out of " + MAX_RETRY_COUNT);
retry = true;
count.decrementAndGet();
}
return retry;
}
}
POM.xml - > Surefire配置:
这是你应该配置“覆盖”surefire监听器的地方,它有自己的计数器。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<suiteXmlFiles><suiteXmlFile>${basedir}/testng.xml</suiteXmlFile></suiteXmlFiles>
<properties>
<property>
<name>listener</name>
<value>Utils.MyTestListenerAdapter,Utils.MyRetryAnalizer</value>
</property>
</properties>
我最终选择了一个使用套件监听器的解决方案。
该解决方案可能无法完全清理TestNG /您的测试记录到控制台的内容,但如果您使用TestNG Jenkins插件,并且每次测试都先失败,然后成功,那么测试运行最终会变为绿色,即I猜是最重要的事情。
是的,我们运行mvn integration-test(不是mvn verify),让TestNG插件处理pass / fail。 The solution is quite similar / builds on what was posted here。
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.testng.ISuite;
import org.testng.ISuiteListener;
import org.testng.ISuiteResult;
import org.testng.ITestContext;
/**
* {@link ISuiteListener} implementation to clean up duplicate test results caused by retrying tests using the
* {@link RetryAnalyzer}
*/
public class SuiteResultListener implements ISuiteListener {
private static final Logger LOG = LogManager.getLogger();
@Override
public void onStart(ISuite suite) {
}
@Override
public void onFinish(ISuite suite) {
LOG.info("Cleaning up duplicate test failures in suite '" + suite.getName() + "' ...");
final Map<String, ISuiteResult> results = suite.getResults();
int removedFailures = 0;
for (ISuiteResult result : results.values()) {
final ITestContext testContext = result.getTestContext();
removedFailures += TestListenerUtil.cleanUpDuplicateFailures(testContext);
}
LOG.info("Removed " + removedFailures + " duplicate test failure(s) from suite '" + suite.getName() + "'");
}
}
这是TestListenerUtil类中发生的魔力:
public static int cleanUpDuplicateFailures(ITestContext testContext) {
final String testContextName = testContext.getName();
int removedFailures = 0;
LOG.info("Cleaning up failures in test context '" + testContextName + "' ...");
final Set<ITestResult> failedTests = testContext.getFailedTests().getAllResults();
if (failedTests.isEmpty()) {
LOG.info("There are no failures in test context '" + testContextName + "'
");
} else {
// collect all id's from passed test
final Set<Integer> passedTestIds = new HashSet<>();
final Set<ITestResult> passedTests = testContext.getPassedTests().getAllResults();
LOG.info("Analyzing " + passedTests.size() + " passed test(s)");
for (ITestResult result : passedTests) {
final int testId = TestListenerUtil.getId(result);
passedTestIds.add(testId);
LOG.info(" Passed test " + TestListenerUtil.getName(result) + ": #" + testId + " @ "
+ getStartTime(result));
}
// check which failed test results should be removed
final List<Integer> resultsToBeRemoved = new ArrayList<>();
final Set<Integer> failedTestIds = new HashSet<>();
LOG.info("Analyzing " + failedTests.size() + " failed test(s)");
for (ITestResult result : failedTests) {
final int testId = TestListenerUtil.getId(result);
final String name = TestListenerUtil.getName(result);
// if we saw this test pass or fail before we mark the result for deletion
if (failedTestIds.contains(testId) || passedTestIds.contains(testId)) {
LOG.info(" Adding test " + name + " to be removed: #" + testId + " @ " + getStartTime(result));
resultsToBeRemoved.add(testId);
} else {
LOG.info(" Remembering failed test " + name + ": #" + testId + " @ " + getStartTime(result));
failedTestIds.add(testId);
}
}
// finally delete all duplicate failures (if any)
final int duplicateFailures = resultsToBeRemoved.size();
if (duplicateFailures > 0) {
LOG.info("Cleaning up failed tests (expecting to remove " + resultsToBeRemoved.size()
+ " result(s)) ...");
for (ITestResult result : testContext.getFailedTests().getAllResults()) {
final int testId = TestListenerUtil.getId(result);
final String info = TestListenerUtil.getName(result) + ": #" + testId + " @ "
+ getStartTime(result);
if (resultsToBeRemoved.contains(testId)) {
LOG.info(" Removing failed test result " + info);
testContext.getFailedTests().removeResult(result);
resultsToBeRemoved.remove((Integer) testId);
removedFailures++;
} else {
LOG.info(" Not removing failed test result " + info);
}
}
}
if (removedFailures == duplicateFailures) {
LOG.info("Removed " + removedFailures + " failed test result(s) in '" + testContextName + "'
");
} else {
LOG.warn("Removed " + removedFailures + " failed test result(s) in '" + testContextName
+ "' (expected to remove " + duplicateF以上是关于通过测试监听器删除(复制)失败的TestNG结果的主要内容,如果未能解决你的问题,请参考以下文章