retryAnalyzer 后如何将 TestNG DefaultSuite 结果发送到 Maven Surefire 插件

Posted

技术标签:

【中文标题】retryAnalyzer 后如何将 TestNG DefaultSuite 结果发送到 Maven Surefire 插件【英文标题】:How to send TestNG DefaultSuite results after retryAnalyzer to Maven Surefire Plugin 【发布时间】:2014-11-26 13:08:24 【问题描述】:

我确实搜索了很多,这是我得到的最接近的答案,但并没有解决我的问题。 TestNG retrying failed tests doesn't output the correct test results

但我需要将上述问题从 TestNG 扩展到 Maven。请帮忙。

我的项目堆栈:TestNG、Maven surefire 插件、Maven。我正在从命令行运行测试 - “mvn clean compile test”。我正在使用重试分析仪重新运行第二次通过的失败测试。我已经能够使用 CustomListener 来更新存储在 TestNG 的 testcontext 中的结果(基于 *** 中的解决方案)。当我作为 TestNG 套件运行测试时,这一点得到了证实。

但是当我运行“mvn clean compile test”时,所有的重试都算作单独的测试并且构建总是失败。如何使 TestNG 仅将最终套件结果发送到 Maven Surefire 插件?

测试执行:

============================================
DefaultTest
Total tests run: 4, Failures: 2, Skips: 0
============================================

============================================
DefaultSuite
Total tests run: 2, Failures: 0, Skips: 0
============================================

MAVEN 执行:

Tests run: 4, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.292 sec <<< FAILURE!

Results :

Failed tests: 
  test1(foo.TestClass1)
  test1(foo.TestClass1)

Tests run: 4, Failures: 2, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------

由于重试,构建通过。如何将 TestNG 重试套件结果反映到 Maven 上?

【问题讨论】:

嗨!你的问题解决了吗?我将问题追踪到 maven testng runner,它将自己的侦听器安装到 testng 中。它忽略最终的计数器调整,因为它维护自己的计数器 这里有同样的问题。任何想法或更新?谢谢! 【参考方案1】:
Some suit info is incorrect, but maven surefire works properly

maven-surefire-plugin 2.16
testng 6.8.8

// ===== InvokedMethodListener =====
import org.testng.IInvokedMethod;
import org.testng.IInvokedMethodListener;
import org.testng.ITestResult;

public class InvokedMethodListener implements IInvokedMethodListener 

    @Override
    public void beforeInvocation(IInvokedMethod method, ITestResult testResult) 
    

    @Override
    public void afterInvocation(IInvokedMethod method, ITestResult testResult) 
        RetryAnalyzer retryAnalyzer = (RetryAnalyzer)testResult.getMethod().getRetryAnalyzer();
        if (retryAnalyzer == null || retryAnalyzer.isFailed()) 
            return;
        
        if (testResult.getStatus() == ITestResult.FAILURE) 
            testResult.setStatus(ITestResult.SUCCESS);
        
    



// ===== RetryAnalyzer =====
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
import org.testng.Reporter;

public class RetryAnalyzer implements IRetryAnalyzer 
    private int count = 0;
    private int maxCount = 2;

    @Override
    public boolean retry(ITestResult result) 
        if (!result.isSuccess()) 
            if (count < maxCount) 
                count++;
                return true;
            
        
        return false;
    

    public boolean isFailed() 
        return count >= maxCount;
    



// ===== BaseTest =====
@Listeners( ..InvokedMethodListener.class )
public abstract class BaseTest 
...
    @BeforeSuite(alwaysRun = true)
    public void beforeSuite(ITestContext context) 
        for (ITestNGMethod method : context.getAllTestMethods()) 
            method.setRetryAnalyzer(new RetryAnalyzer());
        
    

【讨论】:

【参考方案2】:

终于明白了。我使用此代码:

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();
            
        
    
   

重试分析器

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>

【讨论】:

我的测试框架中有类似的设置,但出现以下错误:Listener package.RerunTestAnalyzer@6fda4e65 必须是 ITestListener、ISuiteListener、IReporter、IAnnotationTransformer、IMethodInterceptor 或 IInvokedMethodListener 之一。你知道我该如何解决这个错误吗? 经过一番研究,我发现我们不需要在 pom.xml 中声明我们自定义的 IRetryAnalyzer 实现。由于它不是典型的 TestNG 监听器,所以上面的错误是有效的。此外,纠正执行测试总数的逻辑在 TestListenerAdapter 实现中。只要我们在 pom 文件中声明这个监听器,Maven 就会打印出正确数量的执行测试。

以上是关于retryAnalyzer 后如何将 TestNG DefaultSuite 结果发送到 Maven Surefire 插件的主要内容,如果未能解决你的问题,请参考以下文章

升级intellij后无法运行testNG.xml

Jenkins如何集成运行testng.xml文件的解决方案

编辑后的帖子如何从main()运行TestNG测试,我已经编写了主类 - 但是现在呢?

如何将动态参数传递给 testNG.xml 运行多个测试

TestNG - 如何在 testng 自定义电子邮件报告中打印运行时 testng 参数?

Java--TestNG