基于testng+cucumber的移动端UI自动化重跑实现

UI自动化由于其不稳定性,经常需要维护,为了减少维护的成本,配置失败重跑显得非常重要。

此次失败重跑主要做两件事情:失败的场景重跑 和 报告的更新去重

1、失败重跑

testng有提供重跑的接口,需要实现IRetryAnalyzer接口的retry方法,该方法控制重跑的次数,代码如下:

 

public class Retry implements IRetryAnalyzer {
    private static Logger logger = Logger.getLogger(Retry.class);
    private int retryCount = 1;
    private static int maxRetryCount = 2;//控制失败重跑次数

    @Override
    public boolean retry(ITestResult result){
        logger.info("====执行用例:" + result.getName() + ",第" + retryCount + "次失败!");
        if(retryCount < maxRetryCount){
            retryCount ++;
            return true;
        }
        retryCount = 1;
        return false;
    }
}

其中:

  • retryCount=1这个不能少!因为retry的次数是所有用例公用的,如果前面有失败的用例把retry次数用完,后面再有失败的用例,便不会再重跑了,所以当发现重跑次数达到上限后,将retry次数置为1,这样,后面再有失败的用例,判断发现小于最大执行次数,会继续重跑,不受影响。
  • 当然这里会有一个问题,如果最大执行次数为2时,这种方法没有问题,如果大于2,则当没有达到最大执行次数但又不是1时,再有失败的用例时,重跑的次数会变小。
  • 网上有一种实现方案是在监听器中onTestFailue、onTestSucess等方法中均加上将retry次数置为1的方法,这个方法我尝试之后发现不可行,因为如果一个接口一直是失败的,每次执行后,重跑次数置为1,判断发现小于最大执行次数,仍会继续执行,从而陷入无限循环。

除了实现retry方法外,同时需要一个监听器来监听这个重跑方法:

public class RetryListener implements IAnnotationTransformer {
    @Override
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod){
        IRetryAnalyzer retry = annotation.getRetryAnalyzer();
        if(retry == null){
            annotation.setRetryAnalyzer(Retry.class);
        }
    }
}

 

 

但重跑后势必会导致报告重复,去重方法通过加一个testng的监听器,实现onFinish方法,只记录最后一次的结果,代码如下:

public class TestngListener extends TestListenerAdapter {

    private static Logger logger = Logger.getLogger(TestngListener.class);

    @Override
    public void onTestFailure(ITestResult tr) {
        super.onTestFailure(tr);
        logger.info(tr.getName() + " Failure");
    }

    @Override
    public void onTestSkipped(ITestResult tr) {
        super.onTestSkipped(tr);
        logger.info(tr.getName() + " Skipped");
    }

    @Override
    public void onTestSuccess(ITestResult tr) {
        super.onTestSuccess(tr);
        logger.info(tr.getName() + " Success");
    }

    @Override
    public void onTestStart(ITestResult tr) {
        super.onTestStart(tr);
        logger.info(tr.getName() + " Start");
    }

    @Override
    public void onFinish(ITestContext testContext) {
        super.onFinish(testContext);
        //失败后重跑,记录最后一次结果
        Iterator listOfFailedTests = testContext.getFailedTests().getAllResults().iterator();
        while (listOfFailedTests.hasNext()) {
            ITestResult failedTest = listOfFailedTests.next();
            ITestNGMethod method = failedTest.getMethod();
            if (testContext.getFailedTests().getResults(method).size() > 1) {
                listOfFailedTests.remove();
            }else if(testContext.getPassedTests().getResults(method).size() > 0) {
                listOfFailedTests.remove();
            }
        }
    }
}

 

然后将监听器配置在testng.xml中监听,不然重跑和去重是不会生效的哦~


        
        

 

如果生成的报告是一个testng的报告的话,上述方法已经完美解决问题,但是由于加入了cucumber,生成的报告是cucumber的报告(因为这个报告比较炫酷,实在是不想放弃),所以仍需要对cucumber的报告进行去重。报告样子大体如下:

基于testng+cucumber的移动端UI自动化重跑实现_第1张图片

 

cucumber的报告实际是通过读取cucumber.json文件来生成的,文件大概长这样:

基于testng+cucumber的移动端UI自动化重跑实现_第2张图片

 

其中,一个文件中有几个场景,elements中就会有几个json,上述截图中有两个场景。如果有失败的,并且进行了重跑,则会在这个文件中的elements中生成两个id一模一样的elements子json,只需要进行去重即可。

步骤:

1、遍历cucumber报告下面的所有cucumber_xxx.json文件

2、逐个读取json文件中是否有重复的element,如果有,放入remove列表

3、删除第一个id能匹配上的元素json数据(因为重跑后需要保留最新的那个数据,所以去掉第一次跑的那个数据),刚好调用remove方法可实现

具体代码如下:

def handleDuplicateData(path):
    json_data = getJsonData(path)
    list = []
    removelist=[]
    elements = json_data[0]['elements']
    for element in elements:
        tmpId = element['id']
        if tmpId not in list:
            list.append(tmpId)
        else:
            removelist.append(tmpId)
    print(list)
    print("===removeList:{}".format(removelist))

    for e in elements:
        if e['id'] in removelist:
            elements.remove(e)
            removelist.remove(e['id'])
    json_data[0]['elements'] = elements

    f2 = open(path,"w+",encoding="utf-8")
    f2.write(str(json.dumps(json_data)))
    f2.close()

至此,已完成自动化的重跑和报告的去重了。

你可能感兴趣的:(UI自动化)