Pytest自动化测试框架-权威教程13-Fixture方法及测试用例的参数化

Fixture方法及测试用例的参数化

Pytest在多个级别启用测试参数化:

  • pytest.fixture()允许一个[参数化Fixture方法。

  • @pytest.mark.parametrize允许在测试函数或类中定义多组参数和Fixture。

  • pytest_generate_tests允许用户定义自定义参数化方案或扩展。

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

2.2版中的新函数。

版本2.4中的更改:一些改进。

内置的pytest.mark.parametrize装饰器支持测试函数的参数化。以下是测试函数的示例,该函数实现检查某个输入是否导致预期输出:

Copy# content of test_expectation.pyimport pytest

@pytest.mark.parametrize("test_input,expected",[("3+5",8),("2+4",6),("6*9",42)])deftest_eval(test_input,expected):
    asserteval(test_input) == expected

这里,@parametrize装饰器定义了三个不同的参数,test_input,expected组成元组,以便test_eval函数依次使用它们运行三次:

Copy$ pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y,pytest-4.x.y,py-1.x.y,pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 3 items

test_expectation.py ..F                                              [100%]

================================= FAILURES =================================
____________________________ test_eval[6*9-42] _____________________________

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_expectation.py:6: AssertionError
==================== 1 failed,2 passed in 0.12 seconds ====================
注意: 默认情况下,pytest会转义unicode字符串中用于参数化的任何非ascii字符,因为它有几个缺点。但是,如果你想在参数化中使用unicode字符串并在终端中按原样(非转义)查看它们,请在以下位置使用此选项pytest.ini:
(译者注:需要pytest>=5.0.0, 数据或ids中的中文才能正常显示)
Copy[pytest]disable_test_id_escaping_and_forfeit_all_rights_to_community_support = True

但请记住,这可能会导致不必要的副作用甚至是错误,具体取决于所使用的操作系统和当前安装的插件,因此使用它需要你自担风险。

如本例所示,只有一对输入/输出值无法通过简单的测试用例。和通常的测试函数参数一样,你可以在traceback中看到input和output值。

请注意,你还可以在类或模块上使用参数化标记(请参阅[使用属性标记测试函数),这将使用参数集调用多个函数。

也可以在参数化中标记单个测试实例,例如使用内置mark.xfail:

Copy# content of test_expectation.pyimport pytest

@pytest.mark.parametrize("test_input,expected",
    [("3+5",8),("2+4",6),pytest.param("6*9",42,marks=pytest.mark.xfail)],
)deftest_eval(test_input,expected):
    asserteval(test_input) == expected

我们运行这个:

Copy$ pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y,pytest-4.x.y,py-1.x.y,pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 3 items

test_expectation.py ..x                                              [100%]

=================== 2 passed,1 xfailed in 0.12 seconds ====================

之前导致失败的一个参数集现在显示为“xfailed(预期失败)”测试。

如果提供的值parametrize导致空列表 - 例如,如果它们是由某个函数动态生成的 - 则pytest的行为由该empty_parameter_set_mark选项定义。

要获得多个参数化参数的所有组合,你可以堆叠parametrize装饰器:

Copyimport pytest

@pytest.mark.parametrize("x",[0,1])@pytest.mark.parametrize("y",[2,3])deftest_foo(x,y):
    pass

这将运行与设定参数的测试x=0/y=2,x=1/y=2,x=0/y=3,并x=1/y=3在装饰的秩序排气参数。

基本的pytest_generate_tests例子

有时你可能希望实现自己的参数化方案或实现一些动力来确定Fixture的参数或范围。为此,你可以使用pytest_generate_tests在收集测试函数时调用的钩子。通过传入的metafunc对象,你可以检查请求的测试上下文,最重要的是,你可以调用metafunc.parametrize()以引起参数化。

例如,假设我们想要运行一个测试,我们想通过一个新的pytest命令行选项设置字符串输入。让我们首先编写一个接受stringinputfixture函数参数的简单测试:

Copy# content of test_strings.pydeftest_valid_string(stringinput):
    assert stringinput.isalpha()

现在我们添加一个conftest.py包含命令行选项和测试函数参数化的文件:

Copy# content of conftest.pydefpytest_addoption(parser):
    parser.addoption(
        "--stringinput",
        action="append",
        default=[],
        help="list of stringinputs to pass to test functions",
    )

defpytest_generate_tests(metafunc):
    if"stringinput"in metafunc.fixturenames:
        metafunc.parametrize("stringinput",metafunc.config.getoption("stringinput"))

如果我们现在传递两个stringinput值,我们的测试将运行两次:

Copy$ pytest -q --stringinput="hello" --stringinput="world" test_strings.py
..                                                                  [100%]
2 passed in 0.12 seconds

让我们运行一个stringinput导致测试失败:

Copy$ pytest -q --stringinput="!" test_strings.py
F                                                                    [100%]
================================= FAILURES =================================
___________________________ test_valid_string[!] ___________________________

stringinput = '!'

 def test_valid_string(stringinput):
>       assert stringinput.isalpha()
E       AssertionError: assert False
E        +  where False = <built-in method isalpha of str object at 0xdeadbeef>()
E        +    where <built-in method isalpha of str object at 0xdeadbeef> = '!'.isalpha

test_strings.py:4: AssertionError
1 failed in 0.12 seconds

正如所料,我们的测试用例失败。

如果你没有指定stringinput,它将被跳过,因为metafunc.parametrize()将使用空参数列表调用:

Copy$ pytest -q -rs test_strings.py
s                                                                    [100%]
========================= short test summary info ==========================
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.12 seconds
注意: metafunc.parametrize使用不同的参数集多次调用时,这些集合中的所有参数名称都不能重复,否则将引发错误。

更多示例

有关更多示例,你可能需要查看更多参数化示例。

实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

如果对你有帮助的话,点个赞收个藏,给作者一个鼓励。也方便你下次能够快速查找。

如有不懂还要咨询下方小卡片,博主也希望和志同道合的测试人员一起学习进步

在适当的年龄,选择适当的岗位,尽量去发挥好自己的优势。

我的自动化测试开发之路,一路走来都离不每个阶段的计划,因为自己喜欢规划和总结,

测试开发视频教程、学习笔记领取传送门!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值