一文帶你深入理解python中pytest-repeat插件的工作原理
不使用pytest_repeat插件如何實現(xiàn)重復(fù)執(zhí)行用例
最笨的辦法,當(dāng)然是運行多次,但這顯然不是我們需要的,我們知道裝飾器可以在不修改原始代碼的情況下,動態(tài)的增加功能或修改函數(shù)行為。顯然,這里我們就可以使用裝飾器來實現(xiàn)重復(fù)功能。
def repeat(nums: int = 2): ? ?def wrapper(func): ? ? ? ? ?@functools.wraps(func) ? ? ? ?def decorator(*args, **kwargs): ? ? ? ? ? ?for i in range(nums): ? ? ? ? ? ? ? ?func(*args, **kwargs) ? ? ? ? ?return decorator ? ? ?return wrapper
這段代碼很好理解,定義了帶有自定義參數(shù)的裝飾器,表示裝飾器內(nèi)部函數(shù)執(zhí)行的次數(shù)。這樣在用例上使用@repeat()
裝飾器就可以達到用例重復(fù)運行的目的。但是統(tǒng)計結(jié)果仍然為1條用例。使用過pytest_repeat
的同學(xué)知道它的統(tǒng)計結(jié)果是多條用例?那是如何做的呢,通過源碼一探究竟。
pytest_repeat如何實現(xiàn)重復(fù)執(zhí)行
源碼解讀
def pytest_addoption(parser): ? ?parser.addoption( ? ? ? ?'--count', ? ? ? ?action='/pytest-dev/pytest-repeat/blob/v0.9.1/store', ? ? ? ?default=1, ? ? ? ?type=int, ? ? ? ?help='Number of times to repeat each test') ? ? ?parser.addoption( ? ? ? ?'--repeat-scope', ? ? ? ?action='/pytest-dev/pytest-repeat/blob/v0.9.1/store', ? ? ? ?default='function', ? ? ? ?type=str, ? ? ? ?choices=('function', 'class', 'module', 'session'), ? ? ? ?help='Scope for repeating tests')
這段代碼定義了兩個命令行選項:
--count
:用于指定每個測試用例要重復(fù)執(zhí)行的次數(shù)。action=store
表示將值存儲在命令行參數(shù)中。--repeat-scope
:用于指定重復(fù)測試用例的作用域,可以選擇function
、class
、module
或session
。默認(rèn)值是function
。action=store
表示將值存儲在命令行參數(shù)中。
這兩個選項都是通過 parser.addoption
方法添加到 pytest 的命令行解析器中的。
當(dāng)運行 pytest 并指定 --count
、--repeat-scope
參數(shù)時,pytest-repeat
插件將獲取這些參數(shù)并自動為測試用例生成多個重復(fù)執(zhí)行的實例。
例如,如果運行以下命令:
pytest --count=2 --repeat-scope=function
pytest-repeat
將會在執(zhí)行 test_my_function
測試用例時,自動執(zhí)行該測試用例兩次。
action=store
是 argparse
模塊中的一個參數(shù),它指定了在命令行解析過程中如何處理選項的值。具體地說,action=store
表示將選項的值存儲在命令行參數(shù)中。
當(dāng)使用 parser.addoption
方法添加選項到命令行解析器時,通過指定 action=store
,選項的值將被存儲在解析結(jié)果中,可以通過相應(yīng)的屬性來獲取這些值。
例如,當(dāng)運行 pytest 命令時,指定的 --count
和 --repeat-scope
選項的值會存儲在命令行參數(shù)中。你可以使用 request.config.getoption
方法來獲取這些存儲的值,例如:
def test_example(request): ? ?count = request.config.getoption('--count') ? ?# count = request.config.option.count 這樣也能獲取 ? ?repeat_scope = request.config.getoption('--repeat-scope') ? ?# repeat_scope = request.config.option.repeat_scope ? ?# 使用獲取到的值進行后續(xù)操作
在上面的示例代碼中,使用 request.config.getoption
方法從命令行參數(shù)中獲取了 --count
和 --repeat-scope
的值,并分別存儲在 count
和 repeat_scope
變量中。
總結(jié):action=store
是 argparse
模塊中的一個參數(shù),用于指定將選項的值存儲在命令行參數(shù)中。在 pytest 中,通過使用 request.config.getoption
方法可以獲取存儲在命令行參數(shù)中的選項值。
def pytest_configure(config): ? ?config.addinivalue_line( ? ? ? ?'markers', ? ? ? ?'repeat(n): run the given test function `n` times.')
這個函數(shù)在 pytest 的配置階段被調(diào)用,通過調(diào)用 config.addinivalue_line()
將自定義標(biāo)記 'repeat(n)'
添加到 pytest 的標(biāo)記列表中。'repeat(n)'
標(biāo)記可以用于指定一個測試函數(shù)需要重復(fù)運行的次數(shù)。
@pytest.fixture def __pytest_repeat_step_number(request): ? ?marker = request.node.get_closest_marker("repeat") ? ?count = marker and marker.args[0] or request.config.option.count ? ?if count > 1: ? ? ? ?try: ? ? ? ? ? ?return request.param ? ? ? ?except AttributeError: ? ? ? ? ? ?if issubclass(request.cls, TestCase): ? ? ? ? ? ? ? ?warnings.warn( ? ? ? ? ? ? ? ? ? ?"Repeating unittest class tests not supported") ? ? ? ? ? ?else: ? ? ? ? ? ? ? ?raise UnexpectedError( ? ? ? ? ? ? ? ? ? ?"This call couldn't work with pytest-repeat. " ? ? ? ? ? ? ? ? ? ?"Please consider raising an issue with your usage.")
這個 fixture 函數(shù)用于獲取當(dāng)前的重復(fù)運行步驟編號。它首先檢查測試函數(shù)是否被 'repeat'
標(biāo)記裝飾,并從標(biāo)記中獲取重復(fù)次數(shù)。如果沒有標(biāo)記,則使用命令行參數(shù)中的 --count
參數(shù)作為默認(rèn)值。
@pytest.hookimpl(trylast=True) def pytest_generate_tests(metafunc): ? ?count = metafunc.config.option.count ? ?m = metafunc.definition.get_closest_marker('repeat') ? ?if m is not None: ? ? ? ?count = int(m.args[0]) ? ?if count > 1: ? ? ? ?metafunc.fixturenames.append("__pytest_repeat_step_number") ? ? ? ? ?def make_progress_id(i, n=count): ? ? ? ? ? ?return '{0}-{1}'.format(i + 1, n) ? ? ? ? ?scope = metafunc.config.option.repeat_scope ? ? ? ?metafunc.parametrize( ? ? ? ? ? ?'__pytest_repeat_step_number', ? ? ? ? ? ?range(count), ? ? ? ? ? ?indirect=True, ? ? ? ? ? ?ids=make_progress_id, ? ? ? ? ? ?scope=scope ? ? ? )
這個 pytest_generate_tests
鉤子函數(shù)會在 pytest 收集到所有測試函數(shù)之后被調(diào)用,并且它被設(shè)置為 trylast=True
,以確保在其他鉤子函數(shù)執(zhí)行完畢之后再執(zhí)行。
- 首先,代碼獲取了
metafunc.config.option.count
的值,該值表示測試用例重復(fù)執(zhí)行的次數(shù)。 - 然后,代碼調(diào)用
metafunc.definition.get_closest_marker('repeat')
來獲取測試用例是否有被標(biāo)記為repeat
的 marker。 - 如果有
repeat
的 marker 標(biāo)記,則從 marker 中獲取重復(fù)執(zhí)行的次數(shù),并將其賦值給count
變量。 - 接下來,代碼通過
metafunc.fixturenames.append("__pytest_repeat_step_number")
添加了一個名為__pytest_repeat_step_number
的 fixture 名稱到metafunc
的 fixture 列表中。 - 之后,定義了一個輔助函數(shù)
make_progress_id
,用于生成測試用例的進度標(biāo)識符。 - 根據(jù)
metafunc.config.option.repeat_scope
的值,確定了重復(fù)執(zhí)行的作用域。 - 最后,通過調(diào)用
metafunc.parametrize
來動態(tài)生成測試用例。它使用了range(count)
來生成重復(fù)執(zhí)行的步驟數(shù)量作為參數(shù),并將indirect=True
設(shè)置為在加載 fixture 時進行間接調(diào)用。同時,使用了之前定義的進度標(biāo)識符生成函數(shù)和作用域來設(shè)置參數(shù)化的其他選項。
可以看到最終是通過參數(shù)化來實現(xiàn)的,這也就是為啥重復(fù)執(zhí)行多次能當(dāng)做多條用例。
最后
相信你看我之后依然有很多疑問,fixture
是啥?mark
是啥?參數(shù)request
是啥?鉤子函數(shù)是啥?parametrize
參數(shù)化是啥?這些疑問可以先留著,這片內(nèi)容我們主要講了pytest_repeat
具體實現(xiàn)邏輯,然后引出了這么多知識點,別著急,之后會一個個逐一消滅。
以上就是一文帶你深入理解python中pytest-repeat插件的工作原理的詳細(xì)內(nèi)容,更多關(guān)于python pytest-repeat插件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python光學(xué)仿真面向?qū)ο蠊鈱W(xué)元件類的實現(xiàn)
這篇文章主要為大家介紹了python光學(xué)仿真面向?qū)ο蠊鈱W(xué)元件類的實現(xiàn)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2021-10-10用python生成(動態(tài)彩色)二維碼的方法(使用myqr庫實現(xiàn))
今天小編就為大家分享一篇用python生成(動態(tài)彩色)二維碼的方法(使用myqr庫實現(xiàn)),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-06-06Python運行中頻繁出現(xiàn)Restart提示的解決辦法
在編程的世界里,遇到各種奇怪的問題是家常便飯,但是,當(dāng)你的 Python 程序在運行過程中頻繁出現(xiàn)“Restart”提示時,這可能不僅僅是令人頭疼的小問題,而是隱藏著深層次的原因,本文將深入探討這一現(xiàn)象,并提供解決方案,需要的朋友可以參考下2025-04-04linux mint中搜狗輸入法導(dǎo)致pycharm卡死的問題
這篇文章主要介紹了linux mint中搜狗輸入法導(dǎo)致pycharm卡死的問題,這篇文章給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10淺析python打包工具distutils、setuptools
python包在開發(fā)中十分常見,一般的使用套路是所有的功能做一個python模塊包,打包模塊,然后發(fā)布,安裝使用。這篇文章給大家介紹了python打包工具distutils、setuptools的相關(guān)知識,感興趣的朋友一起看看吧2018-04-04