testng跑失敗用例重試


testng 提高用例通過率,失敗用例要重新運行一次

步驟:

1、新建一個Retry 類,implements IRetryAnalyzer接口,這個類里面確定重跑次數,以及分析每次失敗是否需要重新運行

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

public class Retry implements IRetryAnalyzer {
    private int retryCount = 0;
    private int maxRetryCount = 1;

    @Override
    public boolean retry(ITestResult result) {
        if (retryCount < maxRetryCount) {
            System.out.println("Retrying test " + result.getName() + " with status "
                    + getResultStatusName(result.getStatus()) + " for the " + (retryCount + 1) + " time(s).");
            retryCount++;

            return true;
        }
        resetRetrycount(); // 每次跑完一條用例后,重置retryCount為0,這樣dataProvider 數據驅動測試葉支持
        return false;
    }

    public String getResultStatusName(int status) {
        String resultName = null;
        if (status == 1)
            resultName = "SUCCESS";
        if (status == 2)
            resultName = "FAILURE";
        if (status == 3)
            resultName = "SKIP";
        return resultName;
    }

    public boolean isRetryAvailable() {
        return retryCount < maxRetryCount;
    }

    public void resetRetrycount() {
        retryCount = 0;
    }

}

 

2、新建一個RetryListener類,implements IAnnotationTransformer 主要功能是監聽事件

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 {

    @Override
    public void transform(ITestAnnotation testannotation, Class testClass,
            Constructor testConstructor, Method testMethod)    {
        IRetryAnalyzer retry = testannotation.getRetryAnalyzer();

        if (retry == null)    {
            testannotation.setRetryAnalyzer(Retry.class);
        }

    }
}

3、測試結果處理,testng運行結果中,去掉重復運行的用例,即不論這個用例跑多少遍,都算一個用例

import java.util.Set;

import org.apache.log4j.Logger;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;

public class TestListener implements ITestListener {
    private static org.apache.log4j.Logger logger = Logger.getLogger(ITestListener.class);
    
    @Override
    public void onFinish(ITestContext testContext) {
        // super.onFinish(testContext);

        // List of test results which we will delete later
        ArrayList<ITestResult> testsToBeRemoved = new ArrayList<ITestResult>();
        // collect all id's from passed test
        Set<Integer> passedTestIds = new HashSet<Integer>();
        for (ITestResult passedTest : testContext.getPassedTests().getAllResults()) {
            logger.info("PassedTests = " + passedTest.getName());
            passedTestIds.add(getId(passedTest));
        }

        Set<Integer> failedTestIds = new HashSet<Integer>();
        for (ITestResult failedTest : testContext.getFailedTests().getAllResults()) {
            logger.info("failedTest = " + failedTest.getName());
            // id = class + method + dataprovider
            int failedTestId = getId(failedTest);

            // if we saw this test as a failed test before we mark as to be
            // deleted
            // or delete this failed test if there is at least one passed
            // version
            if (failedTestIds.contains(failedTestId) || passedTestIds.contains(failedTestId)) {
                testsToBeRemoved.add(failedTest);
            } else {
                failedTestIds.add(failedTestId);
            }
        }

        // finally delete all tests that are marked
        for (Iterator<ITestResult> iterator = testContext.getFailedTests().getAllResults().iterator(); iterator
                .hasNext();) {
            ITestResult testResult = iterator.next();
            if (testsToBeRemoved.contains(testResult)) {
                logger.info("Remove repeat Fail Test: " + testResult.getName());
                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 onTestStart(ITestResult result) {
    }

    public void onTestSuccess(ITestResult result) {
    }

    public void onTestFailure(ITestResult result) {
    }

    public void onTestSkipped(ITestResult result) {
    }

    public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
    }

    public void onStart(ITestContext context) {
    }
}  

 

4、testng xml中配置監聽

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Default suite">
<listeners>
        <listener class-name="com.auto.listen1.RetryListener"/>
         <listener class-name="com.auto.listen1.TestListener"/>
  </listeners>
  <test verbose="2" name="Default test">
    <classes>
      <class name="com.auto.listen1.NewTest"/>
    </classes>
  </test> <!-- Default test -->
</suite> <!-- Default suite -->

5、新建一個測試類

package com.auto.listen1;

import org.testng.annotations.Test;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;

//@Listeners(value = MyTestListenerAdapter.class)
public class NewTest {
    @Test(dataProvider = "dp")
    // @Test(retryAnalyzer = MyRetryAnalyzer.class,dataProvider = "dp")
    public void f(Integer n, String s) {
        System.out.println("ssssss:" + s);
        Assert.assertFalse(true);
    }

    }
    @DataProvider
    public Object[][] dp() {
        return new Object[][] { new Object[] { 1, "a" }, new Object[] { 2, "b" },new Object[] { 3, "c" },new Object[] { 4, "d" } };
    }
}

運行結果:

ssssss:a
Retrying test f with status FAILURE for the 1 time(s).
ssssss:a
ssssss:b
Retrying test f with status FAILURE for the 1 time(s).
ssssss:b
ssssss:b
Retrying test f with status FAILURE for the 1 time(s).
ssssss:b
ssssss:c
Retrying test f with status FAILURE for the 1 time(s).
ssssss:c
ssssss:c
Retrying test f with status FAILURE for the 1 time(s).
ssssss:c
ssssss:c
Retrying test f with status FAILURE for the 1 time(s).
ssssss:c
ssssss:d
Retrying test f with status FAILURE for the 1 time(s).
ssssss:d
ssssss:d
Retrying test f with status FAILURE for the 1 time(s).
ssssss:d
ssssss:d
Retrying test f with status FAILURE for the 1 time(s).
ssssss:d
ssssss:d
Retrying test f with status FAILURE for the 1 time(s).
ssssss:d

這個結果中,第一個參數a運行2遍,第二個參數b運行2*2=4遍,第三個參數c運行3*2=6遍,第四個參數d運行4*2=8遍,參數越多運行多余運行次數越多,這個是使用testng 6.9.10 版本問題,更新版本為6.9.13.6 后,運行結果正常如下:

ssssss:a
Retrying test f with status FAILURE for the 1 time(s).
ssssss:a
ssssss:b
Retrying test f with status FAILURE for the 1 time(s).
ssssss:b
ssssss:c
Retrying test f with status FAILURE for the 1 time(s).
ssssss:c
ssssss:d
Retrying test f with status FAILURE for the 1 time(s).
ssssss:d

每個失敗用例都重試一次

 

版本問題參考:https://github.com/cbeust/testng/pull/740

https://github.com/cbeust/testng/pull/1104

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM