pytest fixtures测试函数参数化
Pytest会在以下几个级别启用测试参数化:
- pytest.fixture(),可以对fixture函数进行参数化。
- @pytest.mark.parametrize,可以在测试函数或类中定义多组参数和fixture。
- pytest_generate_tests,可以自定义参数化方案或扩展。
一、@pytest.mark.parametrize:参数化测试函数
1. 常规用法
对测试函数的参数进行参数化,直接使用内置的装饰器pytest.mark.parameterized即可。
1
2
3
4
|
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次。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = 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,这个可以标记测试函数为失败。那么在参数化中,如果想让其中的某个参数运行
的时候测试失败,就可以这样用:
1
2
3
4
5
6
7
|
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 |
运行一下:
1
2
|
test_module1.py [100%] ======================== 2 passed, 1 xfailed in 0.05s =========================..x |
3. 多个参数化组合,笛卡尔积
如果在测试函数上加了多个参数化装饰器,那么得到的参数组合是一个笛卡尔积:
1
2
3
4
5
6
|
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次:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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函数来给测试函数调用。
1
2
3
|
# content of test_strings.py def test_valid_string(stringinput): assert stringinput.isalpha() |
新建conftest.py文件,fixture函数写在这里:
1
2
3
4
5
6
7
8
9
10
11
|
# 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次。
1
2
3
|
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
1
|
FAILED test_strings.py::test_valid_string[!] - AssertionError: assert False1 failed in 0.04s |
如果没有字符串输入,那么测试函数它将被跳过。因为metafunc.parameterize()被调用时,传过去的是一个列表:
pytest -q -rs test_strings.py
1
2
|
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时, 如果使用不同的参数集进行多次参数化,这些参数集上的所有参数名称都不能重复,否则将会报错。
总结
文中讲到的3种用法,实际应用中第一种最常见,第二种次之,至于第三种,可以作为一些用法启发,更多关于pytest fixtures测试函数参数化的资料请关注服务器之家其它相关文章!
原文链接:https://blog.csdn.net/wessonlan/article/details/124813092