一、裝飾器與出錯(cuò)重試機(jī)制保證穩(wěn)定性
談到穩(wěn)定性,不得不說的就是“出錯(cuò)重試”機(jī)制了任斋,在自動(dòng)化測(cè)試中,由于環(huán)境一般都是測(cè)試環(huán)境耻涛,經(jīng)常會(huì)有各種各種的抽風(fēng)情況影響測(cè)試結(jié)果废酷,這樣就為測(cè)試的穩(wěn)定性帶來了挑戰(zhàn),畢竟誰也不想自己的腳本一天到晚的出各種未知問題抹缕,而往往這種環(huán)境的抽風(fēng)(通常是前端頁面的響應(yīng)速度和后端接口的響應(yīng)速度)帶來的影響是暫時(shí)的澈蟆,可能上一秒失敗了,下一秒你再執(zhí)行又好了卓研,在這種情況下趴俘,如果你有一個(gè)出錯(cuò)重試機(jī)制,起碼可以在這種暫時(shí)性的影響下讓你的腳本安然無恙。
裝飾器
裝飾器寥闪,表現(xiàn)形式為带膀,在方法(或者類)的上面加上@xxx這樣的語句,假如我們已經(jīng)實(shí)現(xiàn)了一個(gè)裝飾器名叫retry橙垢,那么我們想用它就這么用:
@retry
def test_login():
print("test")
error = 1/0
如果retry實(shí)現(xiàn)了出錯(cuò)再次重試(稍后再說如何實(shí)現(xiàn))垛叨,那么這么使用的話,就會(huì)讓test_login這個(gè)case在執(zhí)行出錯(cuò)的時(shí)候再次執(zhí)行柜某。
很神奇嗽元,讓我們來看看實(shí)現(xiàn)retry的代碼:
def retry(func):
def warp():
for time in range(3):
try:
func()
except:
pass
return warp
就結(jié)果而言,執(zhí)行以下代碼:
@retry
def test_login():
print("test")
error = 1/0
test_login()
和執(zhí)行:
retry(test_login)()
是等價(jià)的喂击,由此我們可以看出剂癌,裝飾器其實(shí)本質(zhì)上就是一個(gè)函數(shù),這個(gè)函數(shù)接收其他函數(shù)(或者類)作為參數(shù)翰绊,通過對(duì)這個(gè)函數(shù)(或者類)的調(diào)用或者修改佩谷,完成不更改原始函數(shù)而修改該函數(shù)的功能。
這里有個(gè)閉包知識(shí)點(diǎn)监嗜。retry內(nèi)部的函數(shù)warp()并沒有接收func這個(gè)傳參谐檀,而是自帶了上層函數(shù)retry傳給他的func這個(gè)函數(shù),所以才可以在運(yùn)行時(shí)對(duì)func進(jìn)行處理和輸出裁奇。
了解了裝飾器和閉包桐猬,那么下面就很容易做到對(duì)測(cè)試用例的出錯(cuò)重試機(jī)制了。
下面是一個(gè)用于測(cè)試用例的出錯(cuò)重試裝飾器刽肠,可以通過傳入重試次數(shù)(times)和重試等待時(shí)間(wait_time)溃肪,對(duì)待測(cè)用例實(shí)行重試機(jī)制。
def retry(times=3,wait_time=10):
def warp_func(func):
def fild_retry(*args,**kwargs):
for time in range(times):
try:
func(*args,**kwargs)
return
except:
time.sleep(wait_time)
return fild_retry
return warp_func
pytest里的出錯(cuò)重試機(jī)制實(shí)現(xiàn)
在測(cè)試框架pytest里音五,已經(jīng)實(shí)現(xiàn)了有關(guān)出錯(cuò)重試的策略惫撰,我們首先需要安裝一個(gè)pytest-rerunfailures插件。
如果你需要將此機(jī)制應(yīng)用到所有的用例上躺涝,那么請(qǐng)?jiān)趫?zhí)行的時(shí)候使用如下命令(reruns是重試次數(shù)):
pytest --reruns 5
如果你期望加上出錯(cuò)重試的等待時(shí)間厨钻,請(qǐng)使用如下命令(reruns-delay是等待時(shí)間):
pytest --reruns 5 --reruns-delay 1
如果你只想對(duì)某幾個(gè)測(cè)試用例應(yīng)用重試策略,你可以使用裝飾器:
@pytest.mark.flaky(reruns=5, reruns_delay=2)
@pytest.mark.flaky(reruns=5, reruns_delay=2)
def test_example():
import random
assert random.choice([True, False])
二诞挨、測(cè)試用例分層機(jī)制保證可維護(hù)性
傳統(tǒng)的PO(PageObject)模式實(shí)現(xiàn)了用例和元素的分離莉撇,也可以保證其維護(hù)性。但是這還不夠惶傻,例如棍郎,現(xiàn)在有三個(gè)case,他們都包含了以下步驟:登錄银室、打開工作臺(tái)涂佃、進(jìn)入個(gè)人中心励翼;那么如果不做分層,這三個(gè)用例會(huì)把這三個(gè)步驟都寫一遍辜荠,如果某天頁面的變動(dòng)導(dǎo)致其中一個(gè)步驟需要更改伯病,那么你不得不去每個(gè)用例里去更新那個(gè)步驟惭蟋。
而如果,我們把用例當(dāng)做是堆積木,登錄我碟、打開工作臺(tái)卿叽、進(jìn)入個(gè)人中心這三個(gè)步驟都只是個(gè)積木贩虾,那么我們寫用例的時(shí)候,只需要在用到這個(gè)步驟時(shí),把積木搭上去;如果某一天谜嫉,其中一個(gè)積木的步驟有變動(dòng),那么只需要去更改這個(gè)積木的內(nèi)容,而無需在每個(gè)使用了這個(gè)積木的用例里去改動(dòng)。
這大大增強(qiáng)了用例的復(fù)用性和可維護(hù)性,這就是采用分層機(jī)制的原因,下面,我會(huì)就allure里的分層機(jī)制做介紹來討論具體如何實(shí)現(xiàn)。###allure的裝飾器@step
在allure里,我們可以通過裝飾器@step完成分層機(jī)制旨枯,具體的混驰,當(dāng)你用@step裝飾一個(gè)方法時(shí)攀隔,當(dāng)你在用例里執(zhí)行這個(gè)方法,會(huì)在報(bào)告里栖榨,表現(xiàn)出這個(gè)被裝飾方法昆汹;而@step支持嵌套結(jié)構(gòu),這就意味著婴栽,你可以像搭積木一樣去搭你的步驟满粗,而他們都會(huì)一一在報(bào)告里被展示。
下面直接用allure的官方示例作做舉例:
import allure
import pytest
from .steps import imported_step
@allure.step
def passing_step():
pass
@allure.step
def step_with_nested_steps():
nested_step()
@allure.step
def nested_step():
nested_step_with_arguments(1, 'abc')
@allure.step
def nested_step_with_arguments(arg1, arg2):
pass
def test_with_imported_step():
passing_step()
imported_step()
def test_with_nested_steps():
passing_step()
step_with_nested_steps()
運(yùn)行這個(gè)case后居夹,報(bào)告是這樣的:
可以看到败潦,
test_with_nested_steps由passing_step()和step_with_nested_steps()這兩個(gè)方法組成本冲;
而step_with_nested_steps()又由nested_step()組成;
nested_step()又由nested_step_with_arguments(1, 'abc')組成劫扒;
這樣就像搭積木一樣檬洞,組成了測(cè)試用例;而在報(bào)告里沟饥,也層級(jí)分明的標(biāo)識(shí)了步驟的嵌套結(jié)構(gòu)添怔。
這樣,我們就可以通過一個(gè)又一個(gè)@step裝飾的方法贤旷,組成測(cè)試用例广料;同時(shí)報(bào)告里也會(huì)支持層級(jí)顯示;從而完成我們的分層機(jī)制幼驶。
有關(guān)@step的更多詳細(xì)介紹請(qǐng)參閱官方文檔艾杏。
作者:Null_e857
鏈接:http://www.reibang.com/p/474efb786d72
來源:簡書
簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處盅藻。