温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

pytest fixtures函数及测试函数的参数化实例分析

发布时间:2022-06-01 09:29:27 来源:亿速云 阅读:147 作者:zzz 栏目:开发技术

这篇文章主要介绍“pytest fixtures函数及测试函数的参数化实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“pytest fixtures函数及测试函数的参数化实例分析”文章能帮助大家解决问题。

    pytest fixtures测试函数参数化

    Pytest会在以下几个级别启用测试参数化:

    • pytest.fixture(),可以对fixture函数进行参数化。

    • @pytest.mark.parametrize,可以在测试函数或类中定义多组参数和fixture。

    • pytest_generate_tests,可以自定义参数化方案或扩展。

    一、@pytest.mark.parametrize:参数化测试函数

    1. 常规用法

    对测试函数的参数进行参数化,直接使用内置的装饰器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,所以断言失败。

    2. 在参数化中标记单个测试实例

    在参数化中标记单个测试实例,比如之前提到过的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
    3. 多个参数化组合,笛卡尔积

    如果在测试函数上加了多个参数化装饰器,那么得到的参数组合是一个笛卡尔积:

    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 ==============================

    二、用钩子函数pytest_generate_tests example拓展

    如果有些场景需要动态的确定参数或者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()被调用时&#xff0c;传过去的是一个列表:

    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函数及测试函数的参数化实例分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI