測(cè)試的 setup(環(huán)境創(chuàng)建)和 teardown (清除),是每個(gè)自動(dòng)化測(cè)試框架都會(huì)涉及到的概念。簡(jiǎn)單的說, setup 是測(cè)試一個(gè)用例(或者套件)前要做的事情, teardown 是測(cè)試后要做的事情。其實(shí),任何測(cè)試,包括手工測(cè)試都會(huì)涉及到 setup 和 teardown 。
比如,我們有一個(gè) web 系統(tǒng),測(cè)試登錄功能的時(shí)候,需要先注冊(cè)1個(gè)用戶,用這個(gè)用戶驗(yàn)證登錄功能。那么對(duì)于測(cè)試登錄功能的套件(或者用例)來說,前面先注冊(cè)好一個(gè)用戶的操作,就是 setup 。而是否要 teardown ,主要看這個(gè)用例執(zhí)行后的結(jié)果是否會(huì)影響下面要執(zhí)行的用例。比如,我們執(zhí)行了上面用戶登錄的測(cè)試后,,如果要測(cè)試系統(tǒng)的統(tǒng)計(jì)功能,統(tǒng)計(jì)當(dāng)前有多少個(gè)用戶登錄,其中的一個(gè)用例就是,當(dāng)沒有用戶登錄的時(shí)候,顯示登錄數(shù)量為0。這個(gè)時(shí)候就需要前面的用例執(zhí)行完后,必須 teardown ,否則會(huì)影響后面用例的執(zhí)行。由于人具有較高的智能判斷能力,在人工執(zhí)行用例的時(shí)候,會(huì)記憶或者判斷出當(dāng)前的系統(tǒng)的狀態(tài)是否滿足 測(cè)試某個(gè)用例的條件。所以測(cè)試用例書寫的時(shí)候,往往并沒有清除的寫出執(zhí)行前后需要做什么 setup、teardown。而自動(dòng)化測(cè)試軟件就不一樣了,它必須明確每一個(gè)測(cè)試套件(用例)執(zhí)行時(shí)的狀態(tài),否則一旦用例數(shù)量比較大的時(shí)候,就經(jīng)常會(huì)出現(xiàn)由于執(zhí)行前環(huán)境的不同而導(dǎo)致測(cè)試執(zhí)行異常。有的時(shí)候不同的執(zhí)行用例的順序,會(huì)導(dǎo)致同樣的測(cè)試用例和被測(cè)系統(tǒng),這次執(zhí)行成功,下次執(zhí)行失敗。
在 RF 中,每個(gè)測(cè)試套件目錄、測(cè)試套件文件、測(cè)試用例都可以有自己的 setup 和 teardown ,所有的 setup 和 teardown 操作都是由一個(gè)關(guān)鍵字語句構(gòu)成的。
測(cè)試用例的 setup、teardown
- 寫在測(cè)試用例的表的配置項(xiàng)中
*** Test Cases ***
測(cè)試1
[Setup] log to console \n *** case st setup ***
log to console 測(cè)試用例主體部分
[Teardown] log to console \n *** case st teardown ***
這里有一個(gè)測(cè)試用例 Test Cases 叫 測(cè)試1 ,它的配置項(xiàng)就是我們用方括號(hào)括起來的一個(gè)是 [Setup] 一個(gè)是 [Teardown]。
這邊有個(gè)例子:
*** Test Cases ***
測(cè)試1
[Documentation] 測(cè)試初始化、清除
[Setup] log to console \n *** 測(cè)試用例1 setup ****
log to console 測(cè)試用例1主體部分
[Teardown] log to console \n *** 測(cè)試用例 1 teardown ****
測(cè)試2
log to console 測(cè)試用例2主體部分
測(cè)試3
log to console 測(cè)試用例3主體部分
這邊測(cè)試用例有測(cè)試1、測(cè)試2、測(cè)試3,三個(gè)測(cè)試用例,在測(cè)試1里面有方括號(hào)括起來的 [Setup]、[Teardown]。這個(gè)就代表測(cè)試用例1的 [Setup]和[Teardown] ,這邊沒有什么具體的內(nèi)容,我的 [Setup] 和 [Teardown] 只是打了一些 log 我們執(zhí)行一下看一下它的結(jié)果。

我們可以看到首先打印了測(cè)試1的 Setup 接下來是用例1的主體部分,然后是他的 Teardown 這是測(cè)試用例1打印的所有的 log ,在執(zhí)行主體部分之前是 Setup 做的操作,主體部分執(zhí)行完之后是 teardown 的工作,其它的兩個(gè)測(cè)試用例測(cè)試用例2和3只有主體部分,因?yàn)樗麤]有 [Setup] 和 [Teardown] 所以只執(zhí)行主體部分,這個(gè)比較簡(jiǎn)單 [Setup] 和 [Teardown] 一般做一些初始化清除的有實(shí)質(zhì)內(nèi)容的工作,我們這里為了演示只是打印 log,我們看下 log 看看執(zhí)行 log 上的內(nèi)容,也會(huì)記錄初始化與清除的工作的。

這個(gè)是測(cè)試用例的 [Setup] 和 [Teardown] 大家理解一下,接下來看下測(cè)試套件文件的
測(cè)試套件文件的Setup和Teardown
除了測(cè)試用例以外,測(cè)試套件也有初始化與清除,有的人會(huì)想測(cè)試用例中有不就行了嗎,為什么測(cè)試套件里面也要有初始化與清除呢?大家考慮這樣一種情況,因?yàn)槲覀冇械那闆r其實(shí)針對(duì)一個(gè)測(cè)試套件里面所有的用例都需要做的一個(gè)操作,比如說我有一個(gè)用戶登錄的功能,里面有10個(gè)用例,這些用例的初始化都是要?jiǎng)?chuàng)建一個(gè)用戶,舉個(gè)例子:

這里有一個(gè)登陸用戶的用戶名和密碼,用戶名就是abc,密碼就是123,有這樣一個(gè)用戶,這邊用例是創(chuàng)建一個(gè)用戶跟之前的用戶abc密碼123有關(guān)聯(lián)關(guān)系,比如創(chuàng)建一個(gè)test suite1里面t1里面跟已存在的用戶用戶名是一樣的abc密碼不一樣12,然后test case2用戶名不一樣密碼是一樣的,testcase3用戶名ab和密碼12都不一樣。
如果有這樣一個(gè)測(cè)試套件文件,這里面的測(cè)試用例它都需要存在一個(gè)用戶名是abc密碼是123用戶,第一個(gè)用例是創(chuàng)建一個(gè)和用戶名一樣密碼不一樣的用戶,第二是用戶名不一樣密碼一樣,第三用戶名密碼都不一樣,那對(duì)于這種測(cè)試套件里面的測(cè)試用例他是不是共用一個(gè)初始化條件就是有一個(gè)用戶名是abc密碼是123的用戶,如果我們只在每一個(gè)測(cè)試case里面去定義用戶名密碼,十個(gè)用例我要把用戶名為abc密碼123的用戶創(chuàng)建十次,所以因?yàn)檫@個(gè)原因我們?cè)?code>test suite1的初始化里面就創(chuàng)建了這樣一個(gè)abc的用戶,我在下面case執(zhí)行的時(shí)候就不需要在創(chuàng)建了,所以他們共用一套初始化的環(huán)境,我們不需要在每個(gè)初始化的用戶里面都創(chuàng)建這樣一個(gè)用戶,我們只需要在進(jìn)入測(cè)試套件整個(gè)測(cè)試套件文件執(zhí)行之前創(chuàng)建一個(gè)用戶,在所有的測(cè)試套件里面呢每個(gè)用例執(zhí)行完了之后再把它刪掉這樣的話就可以了,有的人會(huì)想既然像之前這種情況,我直接在t1里面創(chuàng)建一個(gè)用戶名為abc密碼為123的用戶,不刪掉,給后面的2,3使用這樣可以嗎??這樣是不可以的,因?yàn)槿绻懊鎰?chuàng)建失敗或者測(cè)試用例失敗, 那后面的就沒有初始化條件測(cè)試就不對(duì)了,還有一種情況你怎么知道我每次執(zhí)行會(huì)選擇所有的用例呢?如果我先執(zhí)行后面的測(cè)試用例最后在執(zhí)行t1或者我根本就不執(zhí)行t1會(huì)有什么問題呢,那我的初始化環(huán)境就沒有了,所以這里給大家強(qiáng)調(diào)測(cè)試用例之間一定不要有相互依賴關(guān)系因?yàn)槟忝看芜x擇測(cè)試用例都是不一樣的比如有冒煙測(cè)試。順序和數(shù)量都是不一樣的所以不能把某個(gè) case 作為其他 case 的依賴,所以我們不能這樣做,這邊就要用到測(cè)試套件文件的 setup、teardown 這是為什么需要他,知道了原因之后我們來看,測(cè)試套件文件的 setup、teardown 。
測(cè)試套件有兩種類型的 Setup 和 Teardown,一個(gè)是 Suite setup/Teardown,一個(gè)是 Test setup/Teardown。其中前者的(suite的)是進(jìn)入這個(gè) suite 執(zhí)行用例前必須執(zhí)行且只執(zhí)行一次。而后者是,如果 suite 內(nèi)的用例本身沒有 setup/Teardown ,才執(zhí)行缺省 setup/Teardown 。后者會(huì)被包含用例的 setup/Teardown 所取代。測(cè)試套件文件的 setup、teardown 是寫在文件的 Settings 表中的。
我們先看第一個(gè) Suite setup/Teardown 例子:
*** Settings ***
Suite Setup log to console \n --- Suite st2 Setup ---
Suite Teardown log to console \n --- Suite st2 Teardown ---
*** Test Cases ***
測(cè)試1
[Setup] log to console \n *** case 測(cè)試1 setup ****
log to console 測(cè)試用例主體部分 11
[Teardown] log to console \n *** case 測(cè)試1 teardown ****
測(cè)試2
log to console 測(cè)試用例主體部分22
測(cè)試3
log to console 測(cè)試用例主體部分33
首先他是放在測(cè)試套件的 Settings 表里面,這個(gè)測(cè)試套件文件有三個(gè)測(cè)試用例第一個(gè)測(cè)試用例有自己的 setup Teardown ,第二個(gè)第三個(gè)沒有,而這個(gè) Suite setup/Teardown 執(zhí)行順序是進(jìn)入測(cè)試套件之前先執(zhí)行 Suite Setup ,所有的用例執(zhí)行完了之后再執(zhí)行 Suite Teardown 我們執(zhí)行一下。

進(jìn)入到測(cè)試 Suite 的之后就執(zhí)行它的 Suite Setup,然后是測(cè)試用例主體的1、2、3部分,全部執(zhí)行完了之后再執(zhí)行 Suite 的 Teardown。大家看到?jīng)],他是包在測(cè)試用例的頭和尾之間的。
下面看一下 Test Setup\Teardown
*** Settings ***
Suite Setup log to console \n --- Suite st Setup ---
Suite Teardown log to console \n --- Suite st Teardown ---
Test Setup log to console \n --- Test st Default Setup ---
Test Teardown log to console \n --- Test st Default Teardown ---
*** Test Cases ***
測(cè)試1
[Setup] log to console \n *** case 1 setup ****
log to console 測(cè)試用例主體部分11
[Teardown] log to console \n *** case 1 teardown ****
測(cè)試2
log to console 測(cè)試用例主體部分22
測(cè)試3
log to console 測(cè)試用例主體部分33
我們除了剛才的 suite setup 之后我們又加了兩個(gè) Test Setup 和 Test Teardown 仍然放在 Settings 表里面的,我們剛說了 Test setup/Teardown 如果用例本事沒有 setup 和 Teardown 我們才用它的,我們看一下這個(gè)測(cè)試套件文件里面有三個(gè)用例,第一個(gè)用例有自己的 setup和Teardown 他還會(huì)用 Test Setup 和 Test Setup Teardown 嗎,如果他有的話它就會(huì)用自己的,測(cè)試用例2和3他們沒有自己的測(cè)試套件初始化和清除那么他就會(huì)用 Test Setup\Teardown 作為它的 Default 的 case 的 setup 和 teardown ,運(yùn)行截圖:

這個(gè)是測(cè)試套件文件的 setup 和 Teardown 除了測(cè)試套件的文件還有測(cè)試套件的目錄呢,測(cè)試套件可以是目錄也可以是文件,測(cè)試套件的文件又可以包含子的套件目錄也可以包含子的文件,比如我們有一些組合目錄登錄功能、注冊(cè)功能都輸入用戶管理功能等等,就是這種一層層組合的,可以加很多目錄出來,我們測(cè)試套件的目錄它也可以有初始化和清除,有沒有覺得奇怪啊,測(cè)試套件文件它對(duì)應(yīng)一個(gè)文件初始化清除就放在文件的Settings 表里面,這個(gè)很容易理解,那么測(cè)試套件目錄他是一個(gè)目錄它的初始化清除對(duì)應(yīng)的語句要放在那里呢?大家來看一下。
測(cè)試套件目錄的 setup Teardown
我們 python 里面都有 package 都有對(duì)應(yīng)的 __init__.py文件,那么 robot 里面測(cè)試套件
目錄的 setup 和 Teardown 它放在他目錄的配置文件 __init__ 這個(gè) Settings 表里面,他可以是 __init__.txt 或者 __init.robot__ 如果這個(gè)文件存在了他就對(duì)應(yīng)這個(gè)目錄的配置文件,我們把它放在這些文件的 settings 表里面。 這個(gè)和 python 是一樣的,而且他們 settings 里面的 setup 和 Teardown 和我們測(cè)試套件文件也非常類似。他也分兩種類型的一種是 Suite ,一種是 Test 大家理解一下.
- 兩種類型
Suite setup/Teardown
進(jìn)入和退出這個(gè)suite執(zhí)行用例前后必須執(zhí)行且只分別執(zhí)行一次Test setup/teardown
如果 suite 內(nèi)的用例、或者子套件本身沒有 setup/teardown ,才執(zhí)行

我這里有個(gè) suit1 有個(gè) st1.robot 和 st2.robot 如果想給 suit1 做一個(gè)初始化清除的文件,那么就需要?jiǎng)?chuàng)建一個(gè) init.robot 大家看一下

__init__.robot里面打印的 log 都叫 Suite big Setup 以及 Test big Default兩種類型(test和suite),這是測(cè)試套件suite1的初始化與清除,這里面有個(gè) St1.robot
*** Settings ***
Suite Setup log to console \n --- Suite little Setup ---
Suite Teardown log to console \n --- Suite little Teardown ---
Test Setup log to console \n --- Test little Default Setup ---
Test Teardown log to console \n --- Test little Default Teardown ---
*** Test Cases ***
測(cè)試1
[Setup] log to console \n *** 測(cè)試用例1 setup ****
log to console 測(cè)試用例1 主體部分
[Teardown] log to console \n *** 測(cè)試用例1 teardown ****
測(cè)試2
log to console 測(cè)試用例2 主體部分
St1 里面又有自己的 Suite Setup/Teardown 和 Test Setup/Teardown,st1 又有測(cè)試用例1和測(cè)試用例2,測(cè)試用例1有自己的測(cè)試用例的 setup 和 Teardown ,還有一個(gè)St2.robot
*** Test Cases ***
測(cè)試3
[Setup] log to console \n *** 測(cè)試用例3 setup ****
log to console 測(cè)試用例3主體部分
[Teardown] log to console \n *** 測(cè)試用例3 teardown ****
測(cè)試4
log to console 測(cè)試用例4主體部分
St2.robot 沒有任何的 Suite Setup/Teardown 但是測(cè)試用例3有他自己的這個(gè) setup 和 Teardown用例4就什么都沒有,我們執(zhí)行下看看,它會(huì)打印出什么東西出來,執(zhí)行之前我們要想一下怎么執(zhí)行呢?這是一個(gè)套件套件怎么執(zhí)行?直接用 robot 直接執(zhí)行 suit1就可以了,整個(gè) suit1 有兩個(gè)測(cè)試用例的文件 st1 和 st2 對(duì)應(yīng)的測(cè)試用例一個(gè)是測(cè)試1測(cè)試2,另一個(gè)是測(cè)試3和測(cè)試4,那我看下他們執(zhí)行的結(jié)果。運(yùn)行結(jié)果有點(diǎn)長(zhǎng),截圖一次截不了我就把結(jié)果復(fù)制了
E:\tmp\rf1>robot suite1
==============================================================================
Suite1
==============================================================================
--- Suite big Setup ---
Suite1.St1
==============================================================================
--- Suite little Setup ---
測(cè)試1
*** 測(cè)試用例1 setup ****
.測(cè)試用例1 主體部分
.
*** 測(cè)試用例1 teardown ****
測(cè)試1 | PASS |
------------------------------------------------------------------------------
測(cè)試2
--- Test little Default Setup ---
.測(cè)試用例2 主體部分
.
--- Test little Default Teardown ---
測(cè)試2 | PASS |
------------------------------------------------------------------------------
--- Suite little Teardown ---
Suite1.St1 | PASS |
2 critical tests, 2 passed, 0 failed
2 tests total, 2 passed, 0 failed
==============================================================================
Suite1.St2
==============================================================================
測(cè)試3
*** 測(cè)試用例3 setup ****
.測(cè)試用例3主體部分
.
*** 測(cè)試用例3 teardown ****
測(cè)試3 | PASS |
------------------------------------------------------------------------------
測(cè)試4
--- Test big Default Setup ---
.測(cè)試用例4主體部分
.
--- Test big Default Teardown ---
測(cè)試4 | PASS |
------------------------------------------------------------------------------
Suite1.St2 | PASS |
2 critical tests, 2 passed, 0 failed
2 tests total, 2 passed, 0 failed
==============================================================================
--- Suite big Teardown ---
Suite1 | PASS |
4 critical tests, 4 passed, 0 failed
4 tests total, 4 passed, 0 failed
==============================================================================
Output: E:\tmp\rf1\output.xml
Log: E:\tmp\rf1\log.html
Report: E:\tmp\rf1\report.html
E:\tmp\rf1>
suite1 有兩個(gè)測(cè)試用例的文件 st1 和 st2 對(duì)應(yīng)的測(cè)試用例測(cè)試1,測(cè)試2,測(cè)試3,測(cè)試4,4個(gè)測(cè)試文件 ,看下執(zhí)行的結(jié)果:首先進(jìn)入 suite1的話他會(huì)先執(zhí)行__init__里面的 Suite Setup log to console |n---Suite big Setup ---和Suite Teardown log to console |n--- Suite big Teardown ---我們整個(gè)測(cè)試套件執(zhí)行最外層開頭和結(jié)尾就應(yīng)該是|n---Suite big Setup ---和|n--- Suite big Teardown ---。
接下來進(jìn)來之后會(huì)執(zhí)行兩個(gè)測(cè)試套件的文件,一個(gè)是 st1 一個(gè)是 st2 ,進(jìn)入st1 的時(shí)候要執(zhí)行測(cè)試用例1之前,他是不是有Suite Setup log to console |n ---Suite little Setup --- Suite Teardown log to console |n --- Suite little Teardown ---這個(gè) Suite Setup/Teard 是不是要包在測(cè)試用例1和測(cè)試用例2外面,因?yàn)槲仪懊娴?strong>Setup是在最外層,這個(gè)里面的應(yīng)該包在1和2外面,應(yīng)該會(huì)有---Suite little Setup ---和--- Suite little Teardown ---包在測(cè)試1和測(cè)試2之間
這個(gè)是包在用例1和2外面的

執(zhí)行完這個(gè) Setup 之后他才執(zhí)行自己內(nèi)部的 setup 和 teardow 首先用例1又有自己的|n *** 測(cè)試用例1 setup ***和|n *** 測(cè)試用例1 Teardown ***那么我們用例1在執(zhí)行主體之前,大家看下主體部分的上和下分別有個(gè)測(cè)試用例1的|n *** 測(cè)試用例1 setup ***和|n *** 測(cè)試用例1 Teardown ***

測(cè)試用例2沒有 steup 和 Teardown 那它是用

st1.robot 中的 Setup teardown 還是

__init__中的Setup teardown,應(yīng)該用離它近的大家記住就近原則,所以測(cè)試2應(yīng)該包在兩邊的是|n --- Test little Default Setup ---和|n --- Test little Default Teardown ---

這是測(cè)試用例1和2//,接下來看一下 st2.robot 里面沒有 Setup 和Teardown,但是測(cè)試3有自己的Setup和Teardown所以3**的外面應(yīng)該包著\n *** 測(cè)試用例3 setup ***和\n *** 測(cè)試用例3 teardown ***

接著看用例4自己沒有Setup和Teardown他所在的st2文件也沒有Setup和Teardown,他就用到了最外層的|n--- Test big Default Setup ---和|n--- Test big Default Teardown ---

我們把suite1里面的4個(gè)測(cè)試用例Setup和Teardown.的順序過了一遍,從過的順序我們了解他們遵循的一個(gè)原則由內(nèi)向外優(yōu)先級(jí)遞減,如果自己有的話就盡量用自己的,沒有的話就往上找
總結(jié):
我們__init_里面的Suite Setup Teardown他只執(zhí)行一次Test Setup Teardown是根據(jù)需要的,如果他沒有的話就會(huì)被多次復(fù)用,如果每個(gè)本身都有的話他可能一次都不會(huì)被用到,Test Setup Teardown每個(gè)用例如果沒有自己Default (缺省)就會(huì)用Test Setup Teardown,如果沒個(gè)用例都有就不會(huì)用到Test Setup Teardown被用的次數(shù)是不固定的。
剛才我們執(zhí)行用例用的命令是:
robot suite1
執(zhí)行了整個(gè)suite1如果我們只想執(zhí)行其中的一個(gè)套件,比如我就想執(zhí)行suite1下st1.robot該怎么執(zhí)行呢,這樣寫是不行的
robot suite1\st1.robot
雖然我運(yùn)行也是執(zhí)行了,

執(zhí)行之后我們看下他的
log,最上層的log是|n ---Suite little Setup ---開始的,|n ---Suite little Setup ---是在st1的Suite Setup但是他最上層的__init__沒有執(zhí)行,因?yàn)槲抑苯泳瓦M(jìn)入到st1去執(zhí)行了,這種情況下比如說我最上層有一些初始化可能就走不到了,這樣是不行的因?yàn)?code>robot關(guān)注的是路徑的最后部分,這里如果想要執(zhí)行應(yīng)該這樣寫我們要執(zhí)行那個(gè)suite就--suite比如st1我們最終是suite1里面的,就是
robot --suite st1 suite1
這樣就執(zhí)行到了:

這個(gè)參數(shù)是告訴robot目標(biāo)參數(shù)是 suite1 里面挑了一個(gè) st1,是這種目的
如果有多個(gè)套件要執(zhí)行就是
`robot --suite st1 --suite st2 suite1
這樣四個(gè)用例就都執(zhí)行了。
--suite指定的就是執(zhí)行的是那個(gè)子套件,如果我就只要執(zhí)行測(cè)試用例1就這樣寫
robot --test 測(cè)試1 suite1
表示:robot suite1 里面的某一個(gè)測(cè)試用例