溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

pytest?fixtures函數(shù)及測(cè)試函數(shù)的參數(shù)化實(shí)例分析

發(fā)布時(shí)間:2022-06-01 09:29:27 來源:億速云 閱讀:145 作者:zzz 欄目:開發(fā)技術(shù)

這篇文章主要介紹“pytest fixtures函數(shù)及測(cè)試函數(shù)的參數(shù)化實(shí)例分析”的相關(guān)知識(shí),小編通過實(shí)際案例向大家展示操作過程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“pytest fixtures函數(shù)及測(cè)試函數(shù)的參數(shù)化實(shí)例分析”文章能幫助大家解決問題。

    pytest fixtures測(cè)試函數(shù)參數(shù)化

    Pytest會(huì)在以下幾個(gè)級(jí)別啟用測(cè)試參數(shù)化:

    • pytest.fixture(),可以對(duì)fixture函數(shù)進(jìn)行參數(shù)化。

    • @pytest.mark.parametrize,可以在測(cè)試函數(shù)或類中定義多組參數(shù)和fixture。

    • pytest_generate_tests,可以自定義參數(shù)化方案或擴(kuò)展。

    一、@pytest.mark.parametrize:參數(shù)化測(cè)試函數(shù)

    1. 常規(guī)用法

    對(duì)測(cè)試函數(shù)的參數(shù)進(jìn)行參數(shù)化,直接使用內(nèi)置的裝飾器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

    從代碼里可以看出,在裝飾器里定義了三個(gè)不同的元組。我們把("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
    拆開看:

    • "test_input,expected":這個(gè)字符串里定義了2個(gè)參數(shù),test_input和expected。

    • ("3+5", 8), ("2+4", 6), ("6*9", 42):這里3個(gè)元組,沒個(gè)元組里有2個(gè)元素,依次序分別對(duì)應(yīng)test_input和expected。

    • 3個(gè)元組外層的[]:列表里就是參數(shù)化具體的傳參了,因?yàn)槔锩鎮(zhèn)髁?個(gè)不同的元組,所以測(cè)試函數(shù)test_eval會(huì)分別執(zhí)行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

    運(yùn)行結(jié)果可以看到最后一次失敗了,因?yàn)榈谌芜\(yùn)行測(cè)試函數(shù)取的參數(shù)是 ("6*9", 42),54不等于42,所以斷言失敗。

    2. 在參數(shù)化中標(biāo)記單個(gè)測(cè)試實(shí)例

    在參數(shù)化中標(biāo)記單個(gè)測(cè)試實(shí)例,比如之前提到過的mark.xfail,這個(gè)可以標(biāo)記測(cè)試函數(shù)為失敗。那么在參數(shù)化中,如果想讓其中的某個(gè)參數(shù)運(yùn)行
    的時(shí)候測(cè)試失敗,就可以這樣用:

    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

    運(yùn)行一下:

    test_module1.py                                                       [100%]
    ======================== 2 passed, 1 xfailed in 0.05s =========================..x
    3. 多個(gè)參數(shù)化組合,笛卡爾積

    如果在測(cè)試函數(shù)上加了多個(gè)參數(shù)化裝飾器,那么得到的參數(shù)組合是一個(gè)笛卡爾積:

    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)

    應(yīng)該會(huì)組合成4組數(shù)據(jù)x=0/y=2, x=1/y=2, x=0/y=3, 和x=1/y=3,測(cè)試函數(shù)執(zhí)行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 ==============================

    二、用鉤子函數(shù)pytest_generate_tests example拓展

    如果有些場(chǎng)景需要?jiǎng)討B(tài)的確定參數(shù)或者fixture的使用范圍,那么可以使用pytest_generate_tests這個(gè)鉤子函數(shù),該函數(shù)會(huì)在收集測(cè)試函數(shù)時(shí)候被調(diào)用。

    通過傳入的metafunc對(duì)象,可以檢查請(qǐng)求測(cè)試函數(shù)的上下文,還可以進(jìn)一步的調(diào)用metafunc.parameterize()來實(shí)現(xiàn)參數(shù)化。

    舉例,有個(gè)測(cè)試函數(shù)需要接受輸入的字符串作為參數(shù),而且通過pytest命令行獲取到,那么就要編寫一個(gè)獲取參數(shù)的fixture函數(shù)來給測(cè)試函數(shù)調(diào)用。

    # content of test_strings.py
    def test_valid_string(stringinput):
        assert stringinput.isalpha()

    新建conftest.py文件,fixture函數(shù)寫在這里:

    # 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"))

    現(xiàn)在用命令行方式來運(yùn)行這個(gè)測(cè)試函數(shù):

    pytest -q --stringinput="hello" --stringinput="world" test_strings.py

    會(huì)運(yùn)行2次。

    D:\PycharmProjects\wms-api\interface\demo>pytest -q --stringinput="hello" --stringinput="world" test_strings.py
    ..                                                                                                                                                                     [100%]
    2 passed in 0.01s

    再換個(gè)輸入?yún)?shù),讓測(cè)試函數(shù)失?。?/p>

    pytest -q --stringinput="!" test_strings.py

    FAILED test_strings.py::test_valid_string[!] - AssertionError: assert False1 failed in 0.04s

    如果沒有字符串輸入,那么測(cè)試函數(shù)它將被跳過。因?yàn)閙etafunc.parameterize()被調(diào)用時(shí)&#xff0c;傳過去的是一個(gè)列表:

    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

    注意,在調(diào)用metafunc時(shí), 如果使用不同的參數(shù)集進(jìn)行多次參數(shù)化,這些參數(shù)集上的所有參數(shù)名稱都不能重復(fù),否則將會(huì)報(bào)錯(cuò)。

    關(guān)于“pytest fixtures函數(shù)及測(cè)試函數(shù)的參數(shù)化實(shí)例分析”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI