您好,登錄后才能下訂單哦!
這篇文章主要介紹“pytest fixtures函數及測試函數的參數化實例分析”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“pytest fixtures函數及測試函數的參數化實例分析”文章能幫助大家解決問題。
Pytest會在以下幾個級別啟用測試參數化:
pytest.fixture(),可以對fixture函數進行參數化。
@pytest.mark.parametrize,可以在測試函數或類中定義多組參數和fixture。
pytest_generate_tests,可以自定義參數化方案或擴展。
對測試函數的參數進行參數化,直接使用內置的裝飾器pytest.mark.parameterized即可。
import pytest @pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)]) def test_eval(test_input, expected): assert eval(test_input) == expected
從代碼里可以看出,在裝飾器里定義了三個不同的元組。我們把("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
拆開看:
"test_input,expected":這個字符串里定義了2個參數,test_input和expected。
("3+5", 8), ("2+4", 6), ("6*9", 42):這里3個元組,沒個元組里有2個元素,依次序分別對應test_input和expected。
3個元組外層的[]:列表里就是參數化具體的傳參了,因為里面傳了3個不同的元組,所以測試函數test_eval會分別執行3次。
============================= test session starts ============================= platform win32 -- Python 3.9.4, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 rootdir: D:\PycharmProjects\wms-api\interface, configfile: pytest.inicollected 3 items test_module1.py ..F demo\test_module1.py:3 (test_eval[6*9-42]) 54 != 42 Expected :42 Actual :54 <Click to see difference> test_input = '6*9', expected = 42 @pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)]) def test_eval(test_input, expected): > assert eval(test_input) == expected E AssertionError: assert 54 == 42 E + where 54 = eval('6*9') test_module1.py:6: AssertionError
運行結果可以看到最后一次失敗了,因為第三次運行測試函數取的參數是 ("6*9", 42),54不等于42,所以斷言失敗。
在參數化中標記單個測試實例,比如之前提到過的mark.xfail,這個可以標記測試函數為失敗。那么在參數化中,如果想讓其中的某個參數運行
的時候測試失敗,就可以這樣用:
import pytest @pytest.mark.parametrize( "test_input,expected", [("3+5", 8), ("2+4", 6), pytest.param("6*9", 42, marks=pytest.mark.xfail)], ) def test_eval(test_input, expected): assert eval(test_input) == expected
運行一下:
test_module1.py [100%] ======================== 2 passed, 1 xfailed in 0.05s =========================..x
如果在測試函數上加了多個參數化裝飾器,那么得到的參數組合是一個笛卡爾積:
import pytest @pytest.mark.parametrize("x", [0, 1]) @pytest.mark.parametrize("y", [2, 3]) def test_foo(x, y): print("\nx:", x) print("y:", y)
應該會組合成4組數據x=0/y=2, x=1/y=2, x=0/y=3, 和x=1/y=3,測試函數執行4次:
test_module1.py . x: 0 y: 2 . x: 1 y: 2 . x: 0 y: 3 . x: 1 y: 3 [100%] ============================== 4 passed in 0.01s ==============================
如果有些場景需要動態的確定參數或者fixture的使用范圍,那么可以使用pytest_generate_tests這個鉤子函數,該函數會在收集測試函數時候被調用。
通過傳入的metafunc對象,可以檢查請求測試函數的上下文,還可以進一步的調用metafunc.parameterize()來實現參數化。
舉例,有個測試函數需要接受輸入的字符串作為參數,而且通過pytest命令行獲取到,那么就要編寫一個獲取參數的fixture函數來給測試函數調用。
# content of test_strings.py def test_valid_string(stringinput): assert stringinput.isalpha()
新建conftest.py文件,fixture函數寫在這里:
# content of conftest.py def pytest_addoption(parser): parser.addoption( "--stringinput", action="append", default=[], help="list of stringinputs to pass to test functions", ) def pytest_generate_tests(metafunc): if "stringinput" in metafunc.fixturenames: metafunc.parametrize("stringinput", metafunc.config.getoption("stringinput"))
現在用命令行方式來運行這個測試函數:
pytest -q --stringinput="hello" --stringinput="world" test_strings.py
會運行2次。
D:\PycharmProjects\wms-api\interface\demo>pytest -q --stringinput="hello" --stringinput="world" test_strings.py .. [100%] 2 passed in 0.01s
再換個輸入參數,讓測試函數失敗:
pytest -q --stringinput="!" test_strings.py
FAILED test_strings.py::test_valid_string[!] - AssertionError: assert False1 failed in 0.04s
如果沒有字符串輸入,那么測試函數它將被跳過。因為metafunc.parameterize()被調用時,傳過去的是一個列表:
pytest -q -rs test_strings.py
SKIPPED [1] test_strings.py: got empty parameter set ['stringinput'], function test_valid_string at $REGENDOC_TMPDIR/test_strings.py:2 1 skipped in 0.12s
注意,在調用metafunc時, 如果使用不同的參數集進行多次參數化,這些參數集上的所有參數名稱都不能重復,否則將會報錯。
關于“pytest fixtures函數及測試函數的參數化實例分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。