`
jerome_wang
  • 浏览: 157154 次
  • 性别: Icon_minigender_1
  • 来自: 云南
社区版块
存档分类
最新评论

Retry executing only Failed Tests using TestNG

 
阅读更多

转自

http://www.cnblogs.com/alterhu/p/3191701.html 

问题情况                                                 

先说下问题情况,最近在做testNG与selenium集成做自动化测试的问题。

因为如果将testNG做UI 测试的话,很多情况下可能测试是失败的,但是这些失败可能是一些其他的问题导致的,可能是脚本的问题或者是网络环境不稳定导致的,所以我们需要重新尝试运行这个失败的测试用例。

testNG倒是没有直接的retry testcase的功能,不过它却提供了很多的接口,我们可以实现这些接口来得到retry的效果。

在google上看到淘宝的QA项目组采用Ruby语言将testNG的源代码修改了retry的功能,然后又重新build后这样做的。这是一个solution,但是我不推荐。原因有两个:

1,修改的jar包是针对指定的testNG版本的,所以如果我们需要体验testNG的新版本功能,这个jar可能就需要在源码基本上重新build有点 不太合适,详细地址是:https://github.com/NetEase/Dagger/wiki/Retry-Failed-Or-Skipped-Testcases

2,该种修改的方法只能使用在testcase级别上,如果需要针对所有的testNG的testsuite都是用这种特性,可能就需要每个testcase都表明他们是使用这个retry功能,有点代码亢余。像这样在testcase中声明retry的类:

import org.apache.log4j.Logger;
import org.testng.Assert;
import org.testng.annotations.Test;

import com.hp.baserunner.RetryFail;
import com.hp.pop.DemoPage;

public class DemoRun {

    private static Logger log=Logger.getLogger(DemoRun.class);
    @Test(retryAnalyzer=RetryFail.class)// 这里声明retry的类,可以看到如果这样每个testcase可能都需要这样做,代码是不是有点多啊 :(
    public void demoTest()
    {
        DemoPage dp=new DemoPage();
        dp.demoTest();
    }
    @Test
    public void demoTest2()
    {
        DemoPage dp2=new DemoPage();
        dp2.demoTest2();
    }
}
既然是框架这样写肯定就有点不太合适了。
框架设计使用                                         
testNG中的对应的提供这些功能的接口有这些:

Interface IRetryAnalyzer   这个就是retrytestcase的一个接口,然后impletment这个接口后实现相应的方法即可:

有一个类 RetryAnalyzerCount  已经实现了以上的这个接口的方法:

package org.testng.util;

import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * An implementation of IRetryAnalyzer that allows you to specify
 * the maximum number of times you want your test to be retried.
 * 
 * @author tocman@gmail.com (Jeremie Lenfant-Engelmann)
 */
public abstract class RetryAnalyzerCount implements IRetryAnalyzer {

  // Default retry once.
  AtomicInteger count = new AtomicInteger(1);

  /**
   * Set the max number of time the method needs to be retried.
   * @param count
   */
  protected void setCount(int count) {
    this.count.set(count);
  }

  /**
   * Retries the test if count is not 0. 
   * @param result The result of the test.
   */
  @Override
  public boolean retry(ITestResult result) {
    boolean retry = false;

    if (count.intValue() > 0) {
      retry = retryMethod(result);
      count.decrementAndGet();
    }
    return retry;
  }

  /**
   * The method implemented by the class that test if the test
   * must be retried or not.
   * @param result The result of the test.
   * @return true if the test must be retried, false otherwise.
   */
  public abstract boolean retryMethod(ITestResult result);
}

 

所以从上面可以看出,如果直接使用继承这个RetryAnalyzerCount 类还是省不少事,直接就可以使用了。

Class TestListenerAdapter

IConfigurationListenerIConfigurationListener2, org.testng.internal.IResultListener, org.testng.internal.IResultListener2, ITestListenerITestNGListener

上面的是另一个类实现了retry的操作的类。这里不使用。

我们今天所使用的是IRetryAnalyzer 接口的,代码如下:

    package com.com.baserunner;
    import org.testng.IRetryAnalyzer;
    import org.testng.ITestResult;
    /**
     * @author sumeetmisri@gmail.com
     * @modify alterhu2020@gmail.com
     * @version 1.0
     * @category
     * 
     */

    public class RetryFail  implements IRetryAnalyzer
    {
        private final int m_maxRetries = 1;
        private final int m_sleepBetweenRetries = 1000;
        private int currentTry;
        private String previousTest = null;
        private String currentTest = null;
        public RetryFail()
        {
            currentTry = 0;
        }

        @Override
        public boolean retry(final ITestResult result)
        {
            // If a testcase has succeeded, this function is not called.        
            boolean retValue = false;        
            
            // Getting the max retries from suite.
           // String maxRetriesStr = result.getTestContext().getCurrentXmlTest().getParameter("maxRetries");
           String maxRetriesStr = result.getTestContext().getSuite().getParameter("maxRetries");
            int maxRetries = m_maxRetries;
            if(maxRetriesStr != null)
            {
                try        
                {
                    maxRetries = Integer.parseInt(maxRetriesStr);
                }
                catch (final NumberFormatException e)
                {
                    System.out.println("NumberFormatException while parsing maxRetries from suite file." + e);
                }
            }
           
            // Getting the sleep between retries from suite.you can from the suite parameter 
            String sleepBetweenRetriesStr = result.getTestContext().getSuite().getParameter("sleepBetweenRetries");
            int sleepBetweenRetries = m_sleepBetweenRetries;
            if(sleepBetweenRetriesStr != null)
            {
                try        
                {
                    sleepBetweenRetries = Integer.parseInt(sleepBetweenRetriesStr);
                }
                catch (final NumberFormatException e)
                {
                    System.out.println("NumberFormatException while parsing sleepBetweenRetries from suite file." + e);
                }
            }
            
            currentTest = result.getTestContext().getCurrentXmlTest().getName();
            
            if (previousTest == null)
            {
                previousTest = currentTest;
            }
            if(!(previousTest.equals(currentTest)))
            {
                currentTry = 0;
            }
           
            if (currentTry < maxRetries &&!result.isSuccess())
            {
                try
                {
                    Thread.sleep(sleepBetweenRetries);
                }
                catch (final InterruptedException e)
                {
                    e.printStackTrace();
                }
                currentTry++;  
                result.setStatus(ITestResult.SUCCESS_PERCENTAGE_FAILURE);
                retValue = true;
                          
            }
            else
            {
                currentTry = 0;
            }
            previousTest = currentTest;
            // if this method returns true, it will rerun the test once again.
            
         
            return retValue;
        }
    }

还有一个lisetner需要加入到testNG的配置文件中:

package com.coma.baserunner;

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 {

    @SuppressWarnings("rawtypes")
    @Override
    public void transform(ITestAnnotation annotation, Class testClass,
            Constructor testConstructor, Method testMethod) {

        IRetryAnalyzer retry = annotation.getRetryAnalyzer();
        if (retry == null) {
            //annotation.setRetryAnalyzer(RetryAnalyzer.class);
            annotation.setRetryAnalyzer(RetryFail.class);
        }
    }

}

然后在testNG的xml的配置文件中如下配置即可:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="FirstSuite" parallel="false" >
 <!--  <parameter name="configfile" value="/resources/config.properties"></parameter> -->
 <parameter name="excelpath" value="resources/TestData.xls"></parameter>
 <listeners>
   <listener class-name="com.com.baserunner.RetryListener"></listener>
 </listeners> 

 



以上的配置方法没有任何问题,唯一的缺陷是,运行的时候testNG的报告中会将retry的testcase的次数也计算在内,所以可能造成,运行后的testcase数目不准确,关于这个问题网上也有人在讨论,可是一直都没有得到一个好的接解决。

最近觉得仔细看看testNG的源代码,看看能不能修改下对应的testNG的报告。使得结果显示的testcase数据与实际的一致,retry的testcase只计算最后一次运行成功的。

如果有结果,再更新。。。。。。。Smile

分享到:
评论

相关推荐

    IAR使用JLINK仿真器调试TI CORTEX-A8开发板

    AM3359开发板,IAR,JLINK 调试步骤清晰,速度很好很快。

    mac vacode 出现文件拒绝修改的问题

    Failed to save ‘index.jsx’: Insufficient permissions. Select ‘Retry as Sudo’ to retry as superuser. EACCES: permission denied 解决方法:授予权限 sudo chmod -R 777 . ## 为当前目录及子目录搜于读写...

    testng-retry-example

    TestNG 重试示例这是一个示例,展示如何使用 TestNG 编写测试,当测试失败时将重试。 当测试代码的行为不是 100% 一致时,它很有用。 在注释中将 retryAnalyzer 与 MyRetryAnalyzer 分开的测试用例将在测试失败时...

    Java测试新技术TestNG和高级概念.pdf

    根据提供的文件信息,我们可以推断出这份文档主要讨论的是关于Java测试新技术TestNG及其高级概念。下面将基于这些信息来生成相关的知识点。 ### TestNG概述 TestNG(Test Next Generation)是一个开源的测试框架,...

    重试框架spring-retry以及guava-retry的使用

    本文将深入探讨两个常用的重试框架:Spring Retry和Guava Retry,并通过一个名为`retry-starter`的Spring Boot项目实例,来解析它们的使用方式以及差异。 首先,我们来看Spring Retry。Spring Retry是Spring框架的...

    springboot基于spring-retry实现重试机制

    Spring Boot 提供了 Spring Retry 模块,它允许我们轻松地在应用中实现重试逻辑。本文将详细探讨如何在 Spring Boot 应用中基于 Spring Retry 实现重试机制,以及如何将其应用于支付回调和自定义重试场景。 首先,...

    python——retry装饰器(csdn)————程序.pdf

    Python retry 装饰器详解 Python 语言中,retry 装饰器是一种非常有用的机制,能够帮助开发者在编写代码时,轻松地实现函数的重试机制。本文将对 Python 中的 retry 装饰器进行详细的讲解,包括其定义、使用方法、...

    spring-retry,.zip

    《Spring Retry:构建健壮应用的关键技术》 在软件开发中,尤其是在分布式系统和网络通信中,偶尔出现的错误和异常是无法避免的。Spring Retry是Spring生态系统中的一个开源项目,它提供了声明性的重试支持,帮助...

    前端开源库-axios-retry

    1. 安装插件:通过npm或yarn进行安装,例如`npm install axios-retry`或`yarn add axios-retry`。 2. 配置插件:在AXIOS实例上启用重试功能,例如`axios.interceptors.response.use(response =&gt; response, error =&gt;...

    spring-retry jar

    spring-retry jar

    前端开源库-superagent-retry

    **超级代理重试库——superagent-retry** 在前端开发中,我们经常遇到网络不稳定、服务器响应延迟等问题,这些问题可能导致API请求失败或者数据获取不完整。为了提高用户体验和应用程序的健壮性,开发者通常需要对...

    kotlin-retry,用于重试可能失败的操作的高阶函数。.zip

    Kotlin-retry是一个专门为Kotlin语言设计的开源项目,它提供了一个高阶函数`retry`,帮助开发者优雅地处理可能失败的操作,并自动进行重试。 `retry`函数的基本思想是,当一个操作在第一次尝试时失败,它可以被自动...

    allure-testng-retry-listener:实现 ITestListener 以允许 Allure Framework 和 TestNG Framework 组合的重试功能

    #Allure TestNG 重试监听器 ITestListener 的实现以允许“重试功能”以结合框架和框架。 请参阅此处的 JavaDocs (TBD)。 ##特征: 如果测试已重试,则其结果状态将从“失败”(“已损坏”)更改为“待定”,并...

    开源项目-shafreeck-retry.zip

    【开源项目-shafreeck-retry】是一个针对Java开发者的开源库,主要目的是提供一种简单易用的重试机制,确保关键操作在遇到异常时能够得到适当处理并最终完成。这个项目的名字“retry”直接表明了其核心功能,即重试...

    spring-retry

    spring-retry-1.0.0.RELEASE.jar

    retry-demo.rar

    本项目"retry-demo.rar"是一个基于Spring Retry的工程示例,用于演示如何在调用失败时实现重试机制。 Spring Retry是一个轻量级的库,它为Java和Spring应用程序提供了简单的API来处理重试逻辑。核心概念包括: 1. ...

    开源项目-Rican7-retry.zip

    开源项目-Rican7-retry.zip,retry - A simple, stateless, functional mechanism to perform actions repetitively until successful

    spring-amqp,spring-retry,spring-rabbit

    标题中的"spring-amqp"、"spring-retry"和"spring-rabbit"是Spring框架的三个关键组件,它们主要用于构建高效、可靠的分布式系统,尤其是在消息传递和错误处理方面。 1. **Spring AMQP**: Spring AMQP是Spring框架...

    Spring Retry实例与原理源码

    在业务场景中 , 有时候会遇到异常后需要重复尝试的操作 , 例如调用三方接口 , 发送邮件/短信 , 推送消息等等 . Spring 提供了Retry组件 , 很方便的解决了上述问题

    node-retry, 失败操作的指数和自定义重试策略的抽象.zip

    node-retry, 失败操作的指数和自定义重试策略的抽象 重试失败操作的指数和自定义重试策略的抽象。安装npm install retry当前状态这个 MODULE 已经测试过了,可以使用了。教程下面的示例将使用指数退避策略重试一个...

Global site tag (gtag.js) - Google Analytics