溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

TestNG測試用例重跑分析

發(fā)布時(shí)間:2021-11-15 11:25:35 來源:億速云 閱讀:105 作者:iii 欄目:移動(dòng)開發(fā)

這篇文章主要講解了“TestNG測試用例重跑分析”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“TestNG測試用例重跑分析”吧!

測試用例運(yùn)行穩(wěn)定性是自動(dòng)化質(zhì)量的一個(gè)重要指標(biāo),在運(yùn)行中需要盡可能的剔除非bug造成的測試用例執(zhí)行失敗,對于失敗用例進(jìn)行重跑是常用策略之一。一種重跑策略是所有用例運(yùn)行結(jié)束后對失敗用例重跑,另一種重跑策略是在運(yùn)行時(shí)監(jiān)控用例運(yùn)行狀態(tài),失敗后實(shí)時(shí)重跑。

下面,詳細(xì)介紹TestNG如何對失敗測試用例實(shí)時(shí)重跑并解決重跑過程中所遇到問題的實(shí)踐和解決方案。對失敗測試用例進(jìn)行實(shí)時(shí)重跑,有以下幾個(gè)方面需求:

  1. 測試用例運(yùn)行失敗,監(jiān)聽到失敗后立即進(jìn)行重跑

  2. 測試用例通過dependsOnMethods/dependsOnGroups標(biāo)記依賴其他測試用例,在被依賴的測試用例重跑運(yùn)行成功后,該測試用例可以繼續(xù)運(yùn)行

  3. 對于重跑多次的測試用例,只記錄最后一次運(yùn)行成功或失敗結(jié)果

第一部分 測試用例重跑

1.1 retryAnalyzer注解方式

對于希望測試用例中的少量易失敗,不穩(wěn)定的測試用例進(jìn)行重跑,可采用這種方式。 

1.1.1 原理

以下是TestNG處理測試用例運(yùn)行結(jié)果的部分代碼。

IRetryAnalyzer retryAnalyzer = testMethod.getRetryAnalyzer();
boolean willRetry = retryAnalyzer != null && status == ITestResult.FAILURE && failure.instances != null && retryAnalyzer.retry(testResult);
if (willRetry) {
  resultsToRetry.add(testResult);
  failure.count++;
  failure.instances.add(testResult.getInstance());
  testResult.setStatus(ITestResult.SKIP);
} else {
  testResult.setStatus(status);
  if (status == ITestResult.FAILURE && !handled) {
    handleException(ite, testMethod, testResult, failure.count++);
  }

分析以上代碼,其中,接口IretryAnalyzer的方法retry()的返回值作為是否對失敗測試用例進(jìn)行重跑的一個(gè)條件。如果retry()結(jié)果為true,則該失敗測試用例會(huì)重跑,同時(shí)將本次失敗結(jié)果修改為Skip;如果結(jié)果為false,則失敗的測試用例保持失敗結(jié)果,運(yùn)行結(jié)束。因此,如果你希望失敗測試用例重跑的話,需要把IretryAnalyzer的retry()方法重寫,插入自己定義的邏輯,設(shè)置返回值為true。

1.1.2 代碼

創(chuàng)建類RetryImpl,重寫retry()方法,設(shè)置失敗測試用例的重跑次數(shù),代碼如下,:

public class RetryImpl implements IRetryAnalyzer {
    private int count = 1;
    private int max_count = 3;   // Failed test cases could be run 3 times at most
    @Override
    public boolean retry(ITestResult result) {
        System.out.println("Test case :"+result.getName()+",retry time: "+count+"");
        if (count < max_count) {
            count++;
            return true;
        }
        return false;
    }
}

1.1.3 實(shí)例

public class TestNGReRunDemo {
    @Test(retryAnalyzer=RetryImpl.class)    
    public void test01(){
        Assert.assertEquals("success","fail");
        System.out.println("test01");
    }
}

以上測試用例test01可重復(fù)運(yùn)行3次。

1.2 實(shí)現(xiàn)接口IAnnotationTransformer方法

如果希望所有失敗的測試用例都進(jìn)行重跑,采用retryAnalyzer注解方式對每個(gè)測試用例進(jìn)行注解就比較麻煩。通過實(shí)現(xiàn)IAnnotationTransformer接口的方式,可以對全量測試用例的重試類進(jìn)行設(shè)置。 該接口是一個(gè)監(jiān)聽器接口,用來修改TestNG注解。IAnnotationTransformer監(jiān)聽器接口只有一個(gè)方法:transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod). 上文中,我們自定義了類RetryImpl 實(shí)現(xiàn)接口IRetryAnalyzer。TestNG通過transfrom()方法修改retryAnalyzer注解。以下代碼對retryAnalyzer注解進(jìn)行修改設(shè)置。

1.2.1代碼

創(chuàng)建類RetryListener,代碼如下。

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

1.2.2 配置Listener

TestNG可以在配置文件或者測試類中對Listener類進(jìn)行配置。

  • 方法一:在TestNG的配置XML中進(jìn)行以下配置

<listeners>
    <listener class-name="PackageName.RetryListener"></listener>
</listeners>
  • 方法二在測試類中通過@Listeners配置

@Listeners({RetryListener.class})   
public class TestNGReRunDemo {
    @Test
    public void test01(){
        Assert.assertEquals("success","fail");
        System.out.println("test01");
    }
}

配置完成后,運(yùn)行測試用例test01,運(yùn)行結(jié)果顯示test01將重跑次數(shù)3次。

第二部分 被依賴的測試用例重跑結(jié)果處理

進(jìn)一步分析TestNG的運(yùn)行代碼,其在對失敗運(yùn)行用例重跑時(shí),邏輯如下圖。TestNG測試用例重跑分析對于通過dependsOnMethods dependsOnGroups注解依賴于其他測試用例的測試用例來講,測試用例執(zhí)行分為兩種情況:

  • alwaysRun=true,則無論所依賴的測試用例執(zhí)行情況如何,該測試用例都會(huì)執(zhí)行,即所依賴的測試用例重跑不會(huì)影響該測試用例的執(zhí)行。

  • alwaysRun=false,或者保持缺省值(false),依賴于其他測試用例或測試用例組的測試結(jié)果,在運(yùn)行時(shí)TestNG獲取所依賴的測試用例的運(yùn)行結(jié)果,檢查依賴的測試用例是否全部執(zhí)行成功,如果不全部成功,則把該測試用例結(jié)果設(shè)置為Skipped。

2.1 場景分析:場景一

被依賴的測試用例失敗后進(jìn)行了重跑,并重跑成功。(注:在RetryImpl類中,已設(shè)置最大重跑次數(shù)max_count = 3

public static int number =0;
@Test
public void test01(){
number++;
System.out.println(String.valueOf(number));
Assert.assertEquals(number,2);
    System.out.println("test01");
}
@Test(dependsOnMethods = "test01")    // alwaysRun = false by default
public void test02(){
    System.out.println("test02 is running only if test01 is passed.");
}
1、TestNG測試報(bào)告

TestNG測試用例重跑分析

2、問題
測試用例運(yùn)行次數(shù)運(yùn)行情況測試報(bào)告
Test012第一次:skipped ; 第二次:passed在Skipped 和Passed的統(tǒng)計(jì)數(shù)量中,test01被分別記錄一次
Test020Skipped記錄一次Skipped
  • 測試報(bào)告:test01運(yùn)行結(jié)果全部被記錄,而用例重跑,只希望記錄最后的結(jié)果。

  • 運(yùn)行情況:測試用例test02依賴于測試用例test01運(yùn)行結(jié)果,在test01重跑成功后,測試用例test02沒有執(zhí)行,不符合需求預(yù)期。

2.2 場景分析:場景二

被依賴的測試用例失敗后進(jìn)行了重跑,并且重跑沒有成功。(注:在RetryImpl類中,已設(shè)置最大重跑次數(shù)max_count = 3)

public static int number =0;
@Test
public void test01(){
number++;
System.out.println(String.valueOf(number));
Assert.assertEquals(number,10);     
    System.out.println("test01");
}
@Test(dependsOnMethods = "test01")    // alwaysRun = false by default
public void test02(){
    System.out.println("test02 is running only if test01 is passed.");
}
1、TestNG測試報(bào)告

TestNG測試用例重跑分析

2、問題
測試用例運(yùn)行次數(shù)運(yùn)行結(jié)果測試報(bào)告
Test013第一次:skipped;第二次:skipped;第三次:failed在Skipped統(tǒng)計(jì)數(shù)量中,test01被被記錄兩次在failed統(tǒng)計(jì)中,test01被記錄一次
Test020Skipped記錄一次Skipped
  • 運(yùn)行情況:測試用例test02依賴于測試用例test01運(yùn)行結(jié)果,在test01重跑失敗后,測試用例test02沒有執(zhí)行,這種情況符合需求預(yù)期。

  • 測試報(bào)告:同場景一,test01重跑失敗,運(yùn)行結(jié)果全部被記錄,而用例重跑,只希望記錄最后的結(jié)果。

第三部分 優(yōu)化解決方案

以下方案解決重跑測試用例成功后后繼測試用例無法繼續(xù)運(yùn)行的問題,并對測試報(bào)告進(jìn)行優(yōu)化。

3.1 TestListenerAdapter方法重寫

根據(jù)上面分析的TestNG邏輯,在對依賴測試用例的結(jié)果進(jìn)行檢查時(shí),如果忽略重跑的中間結(jié)果只檢查最后一次的運(yùn)行結(jié)果,可以達(dá)到需求的目的。對于測試報(bào)告,同樣的處理方式,忽略所有中間的測試用例運(yùn)行結(jié)果,只記錄最后結(jié)果。 測試用例的中間運(yùn)行結(jié)果為Skipped,下面的代碼通過重寫TestListenerAdapteronTestSuccess()onTestFailure()方法,對測試用例的中間結(jié)果skipped進(jìn)行了刪除。代碼如下:

public class ResultListener extends TestListenerAdapter {
    @Override
    public void onTestFailure(ITestResult tr) {
        if(tr.getMethod().getCurrentInvocationCount()==1)
        {
            super.onTestFailure(tr);
            return;
        }
        processSkipResult(tr);
        super.onTestFailure(tr);
    }
    @Override
    public void onTestSuccess(ITestResult tr) {
       if(tr.getMethod().getCurrentInvocationCount()==1)
        {
            super.onTestSuccess(tr);
            return;
        }
        processSkipResult(tr);
        super.onTestSuccess(tr);
    }
   // Remove all the dup Skipped results
    public void processSkipResult(ITestResult tr)
    {
        ITestContext iTestContext = tr.getTestContext();
        Iterator<ITestResult> processResults = iTestContext.getSkippedTests().getAllResults().iterator();
        while (processResults.hasNext()) {
            ITestResult skippedTest = (ITestResult) processResults.next();
            if (skippedTest.getMethod().getMethodName().equalsIgnoreCase(tr.getMethod().getMethodName()) ) {
                processResults.remove();
            }
        }
    }
}

3.2 配置結(jié)果處理Listener類

在配置文件進(jìn)行全局設(shè)置或者在測試類中標(biāo)記。

  • 方法一:在TestNG的配置XML中進(jìn)行以下配置

<listeners>
    <listener class-name="PackageName.ResultListener"></listener>
</listeners>
  • 方法二:在測試類中通過@Listeners配置

@Listeners({ResultListener.class})   
public class TestNGReRunDemo {
    @Test
    public void test01(){
        Assert.assertEquals("success","fail");
        System.out.println("test01");
    }
}

3.3 場景一

1、 結(jié)果驗(yàn)證

TestNG測試用例重跑分析

2、結(jié)果分析:
測試用例運(yùn)行次數(shù)運(yùn)行結(jié)果測試報(bào)告
Test012第一次:skipped;第二次:passed只在Passed的統(tǒng)計(jì)數(shù)量中test01被記錄一次
Test021Passed記錄一次passed

3.4 場景二

1、結(jié)果驗(yàn)證

TestNG測試用例重跑分析

2、結(jié)果分析:
測試用例運(yùn)行次數(shù)運(yùn)行結(jié)果測試報(bào)告
Test013第一次:skipped;第二次:skipped;第三次:failedtest01只在failed統(tǒng)計(jì)中被記錄一次
Test021Skipped依賴用例執(zhí)行失敗,test02結(jié)果為Skipped,只記錄一次結(jié)果Skipped

感謝各位的閱讀,以上就是“TestNG測試用例重跑分析”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對TestNG測試用例重跑分析這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI