自動化測試實戰技巧:「用例失敗重試機制」實現方案分享

狂師發表於2020-06-23

1. 背景說明

在開展自動化測試工作時,經常會由於一些外在原因(如網路中斷、返回超時)導致自動化測試用例執行失敗,而這些失敗並不是用例本身驗證或被測程式存在Bug而引起的,更可氣的是這些失敗場景有可能還是偶發的,為了保證測試用例執行的穩定性驗證有效性,我們需要一種針對失敗用例重試的執行機制。

今天給大家分享的主題:自動化測試工作中,用例指令碼失敗重試機制的實現方式。

結合自動化測試框架來講,用例執行失敗重試機制,通常有三種形式來實現:

  • 藉助依賴框架自身是否有用例失敗重試執行機制。

  • 從用例指令碼自身邏輯處入手,實現失敗執行重試。(適用於被特殊處理過的用例邏輯)

  • 從擴充套件框架原始碼,自定義失敗重試執行機制。(通常適合於所有失敗用例)

接下來,我們以Robot Framework框架為例,以具體的實戰示例專案介紹如何實現用例失敗重試機制。

2. 示例專案環境搭建

為了便於演示,重新建立一套新的虛擬隔離環境,用於搭建Robot Framework框架,操作步驟如下。

1、建立虛擬環境robotframework_env

python3 -m venv robotframework_env

2、啟用虛擬環境

cd robotframework_env
source bin/activate

3、在虛擬環境中,安裝robotframework、robotframework-ride庫(安裝最新即可)。

pip install robotframework
pip install robotframework-ride

如下圖所示:

4、 輸入命令:bin ./ride.py啟動RIDE,如下圖所示。

PS: 其它三方庫演示專案中,暫不需要,讀者可根據實際需求,自行安裝。

3. 建立實戰示例專案

1、 建立trainning演示專案,並在專案下,建立失敗重試機制實戰目錄,並依次建立測試套件、測試用例,示例結構如下:

2、 編寫測試用例,測試用例邏輯如下:

*** Settings ***
Library           Collections

*** Test Cases ***
Class_01_隨機取數,模擬隨機出現失敗場景
    @{list}=    create list    1    2    3
    ${random_num}=    Evaluate    random.choice(${list})    random
    log    ${random_num}
    should be true    ${random_num}==2
  • 在測試用例中,先通過create list關鍵字建立了一個名稱為${list}的列表變數,並依次存入1、2、3三個元素。
  • 再通過Evaluate萬能關鍵字,結合random.chocie方法,從${list}列表中隨機取出一個整型元素,儲存到名稱為${random_num}變數中。
  • 最後,通過should be true關鍵字,斷言${random_num}變數等於2,由於第二步的隨機取值,會讓${random_num}變數值具有隨機性(可能等於2,也可能是1或3),從而實現模擬一條隨機失敗的用例場景。

執行成功結果:

執行失敗結果:

4. 用例失敗重試機制實現

Robot Framework 官方並沒有提供類似retry等引數來配置失敗用例重執行。僅僅提供了--rerunfailed引數對基於結果檔案output.xml來選擇重新執行失敗的用例。

4.1 基於RF框架自身的重試機制

1、 以第3節中新建的示例專案為例,為了便於演示,以命令列來操作,在命令列中輸入執行用例命令,並且將輸出檔案儲存到original.xml檔案中。

robot --output original.xml .

2、 重新執行測試用例,並將第二次執行的結果檔案輸出儲存到rerun.xml檔案中。

robot --output rerun.xml --rerunfailed original.xml .

3、合併兩次執行的結果輸出檔案。

rebot --merge original.xml rerun.xml

在Robot Framework中除了有--rerunfailed引數針對失敗的測試用例外,也有針對測試套件的--rerunfailedsuites,引數詳細說明如下:

-R --rerunfailed output  Select failed tests from an earlier output file to be
                          re-executed. Equivalent to selecting same tests
                          individually using --test option.

------------------------------------------------
 -S --rerunfailedsuites output  Select failed suite from an earlier output file
                          to be re-executed. New in RF 3.0.1.

  • -R--rerunfailed引數非常有用,它的作用是從output file中選擇失敗的用例重跑。但是有個問題,如果上一次執行時用例全部成功,此時加上-R引數再去執行用例時會報錯: failed: All tests passed ,這導致我沒辦法在jenkins job中使用這個引數。

  • -S--rerunfailedsuites引數和-R引數的作用類似,它的作用是從output file中選擇失敗的用例套件重跑。

4.2 基於用例指令碼邏輯重試機制

第二種方法,我們介紹,如何基於用例指令碼邏輯特殊改造,實現用例失敗後的重試機制。

基於用例邏輯增加重試機制,核心實現思路:基於RF內建變數${TEST_STATUS}獲取用例執行結果,再結合Teardown執行改造後的關鍵字邏輯即可。

操作如下:

1、對示例1中的Class_01 測試用例進行改造,抽取用例邏輯部分,存放到單獨的關鍵字下,名稱如測試用例關鍵字

*** Keywords ***
測試用例關鍵字
    @{list}=    create list    1    2    2
    ${random_num}=    Evaluate    random.choice(${list})    random
    log    ${random_num}
    should be true    ${random_num}==2

2、 新增關鍵字用例重試機制,增加用例重試機制的處理邏輯:

*** Keywords ***
用例重試機制
    [Arguments]    ${times}
    ${status}=    set variable    ${TEST STATUS}
    FOR    ${index}    IN RANGE    ${times}
        log    第${index+1}執行結果: ${status}
        Exit For loop if    '${status}'=='PASS' or '${status}'=='True'
        log    第${index+1}次重試執行
        ${status}=    Run keyword And Return Status    測試用例關鍵字
    END

用例重試機制關鍵字中,先通過${TEST STATUS}內建變數,獲取用例執行結果,並且接收變數${times}用於控制重試次數,如果用例執行狀態等於PASS則直接退出重試,否則呼叫Run keyword And Return Status關鍵字繼續執行測試用例。

3、為了便於演示,增加一條名稱為Class_02測試用例,內容如下:

Class_02_隨機取數,模擬隨機出現失敗場景
    測試用例關鍵字
    [Teardown]    run keyword    用例重試機制    5

到此, 我們已經在用例邏輯層面實現了用例失敗重試機制了。

PS: 針對用例邏輯層面實現重試機制,也可以採用關鍵字: Wait Until Keyword Succeeds,讀者可根據自身需求進行改造,本文的用例重試機制並不是唯一的方法。

4.3 基於框架原始碼實現重試機制

除了上述兩種方法,最後一種方法是基於框架層面進行改造,增加全域性重試機制,

通過改寫Robot Framework原始碼增加--retry選項,實現test級別的失敗用例自動再執行,比如用例失敗後,會重新執行N次,直至成功or 耗盡重試次數,生成的日誌和報告檔案中只會體現最後一次執行的結果。

類似如下命令格式:

robot --retry 3 trainning

具體實現:

1、修改檔案 : robotframework_env/lib/python3.7/site-packages/robot/run.py,在USAGE變數裡新增retry引數。

 -F --extension value     Parse only files with this extension when executing
                          a directory. Has no effect when running individual
                          files or when using resource files. If more than one
                          extension is needed, separate them with a colon.
                          Examples: `--extension txt`, `--extension robot:txt`
                          New in RF 3.0.1. Starting from RF 3.2 only `*.robot`
                          files are parsed by default.
 -N --name name           Set the name of the top level suite. By default the
                          name is created based on the executed file or
                          directory.
 -H --retry retry     Set the retry times if test failed.

2、在run.py檔案,RobotFramework類增加make方法,並在開始之前匯入庫from xml.dom import minidom

def make(self, outxml):
        xmldoc = minidom.parse(outxml)
        suiteElementList = xmldoc.getElementsByTagName('suite')
        mySuite = []
        for suiteElement in suiteElementList:
            if suiteElement.childNodes is not None:
                for element in suiteElement.childNodes:
                    if element.nodeName == 'test':
                        mySuite.append(suiteElement)
                        break
        for suite in mySuite:
            testElements = {}
            for element in suite.childNodes:
                if element.nodeName == 'test':
                    name = element.getAttribute('name')
                    if testElements.get(name) == None:
                        testElements.update({name: [element]})
                    else:
                        testElements.get(name).append(element)
            for n, el in testElements.items():
                for i in el[0:-1]:
                    textElement = i.nextSibling
                    suite.removeChild(i)
                    suite.removeChild(textElement)
        savefile = open(outxml, 'w')
        root = xmldoc.documentElement
        root.writexml(savefile)
        savefile.close()

3、RobotFramework類的main方法,加入紅色內容 self.make(settings.output)

4、 開啟robot/conf/setting.py檔案,修改_cli_opts字典,增加'Retry': ('retry', 3),,如下所示:

5、開啟robot/model/itemlist.py檔案,修改visit方法:

    def visit(self, visitor):
        for item in self:
            if self.__module__ == 'robot.model.testcase' and hasattr(visitor, "_context"):
                testStatus = ''
                for i in range(0, int(visitor._settings._opts['Retry'])):
                    if testStatus != 'PASS':
                        if item.name in visitor._executed_tests:
                            visitor._executed_tests.pop(item.name)
                        item.visit(visitor)
                        testStatus = visitor._context.variables['${PREV_TEST_STATUS}']
                    else:
                        break
            else:
                item.visit(visitor)

6、做完如上配置之後,我們來驗證一下引數是否配置成功了,輸入robot —help檢視一下配置引數項。

7、 輸入如下命令,結合Class_01用例,驗證用例失敗重試機制:

robot --test Class_01_隨機取數,模擬隨機出現失敗場景 --retry 3 .

如果測試用例執行結果為PASS,執行一次即正常結束,如果用例執行失敗,則會重試3次執行。

5. 小結

本文以Robot Framework框架為例,介紹了在自動化測試過程中,如何實現用例指令碼失敗重試機制,並且分享了三類實現思路:

  • 藉助依賴框架自身是否有用例失敗重試執行機制。

  • 從用例指令碼自身邏輯處入手,實現失敗執行重試。(適用於被特殊處理過的用例邏輯)

  • 從擴充套件框架原始碼,自定義失敗重試執行機制。(通常適合於所有失敗用例)

認真品味本文的讀者,會發現,雖然本文內容是以Robot Framework框架為例,但其實任何自動化測試框架,要實現測試用例指令碼重試機制,都繞不開本文所提到的三類實現方式思路。學會變通、靈活運用才是王道

希望對大家在實施自動化測試工作當中有所幫助或啟發!如果覺得有用,不用以身相許,關注一下就行

原文傳送門: 原文閱讀

相關文章