pytest - 参数化
目录
参数化:单个参数
# 参数化:单个参数
语法:`@pytest.mark.parametrize(参数变量,['数值1', '数值2',...])`
demo:
```python
"""
pytest 参数化演示:单个值
"""
import pytest
class TestDemo(object):
@pytest.mark.parametrize('name', ['张飞', '关羽', '刘备'])
def test_demo01(self, name):
print("my name is %s " % name)
if __name__ == '__main__':
pytest.main(['-s', '07_pytest_parameterized.py'])
结果:
============================= test session starts =============================
collecting ... collected 3 items
07_pytest_parameterized.py::TestDemo::test_demo01[\u5f20\u98de] my name is 张飞
PASSED
07_pytest_parameterized.py::TestDemo::test_demo01[\u5173\u7fbd] my name is 关羽
PASSED
07_pytest_parameterized.py::TestDemo::test_demo01[\u5218\u5907] my name is 刘备
PASSED
============================== 3 passed in 0.01s ==============================
参数化:多个参数
语法:@pytest.mark.parametrize('参数1,参数2,...', [(), (),(),])
demo:
"""
pytest 参数化:多个参数演示
"""
import pytest
class TestDemo(object):
# 注意:
# 1.name 和 age 是在一个字符串中
# 2.参数值的格式必须是[(), (), ()]
@pytest.mark.parametrize('name, age', [('刘备', 35), ('张飞', 25), ('关羽', 29)])
def test_method(self, name, age):
print("my name is %s , I'm %d year old" % (name, age))
if __name__ == '__main__':
pytest.main(['-s', '08_pytest_parameterize.py'])
结果:
============================= test session starts =============================
collecting ... collected 3 items
08_pytest_parameterize.py::TestDemo::test_method[\u5218\u5907-35] my name is 刘备 , I'm 35 year old
PASSED
08_pytest_parameterize.py::TestDemo::test_method[\u5f20\u98de-25] my name is 张飞 , I'm 25 year old
PASSED
08_pytest_parameterize.py::TestDemo::test_method[\u5173\u7fbd-29] my name is 关羽 , I'm 29 year old
PASSED
============================== 3 passed in 0.01s ==============================
多个参数化
一个测试用例可以标记多个@pytest.mark.parametrize
import pytest
@pytest.mark.parametrize('test_input',[1,2,3])
@pytest.mark.parametrize('test_output,expect', [(4,5),(6,7)])
def test_multi(test_input, test_output, expect):
pass
out:
PS E:\PyProject\pytestDemo> pytest -rA -s
======================================================================= test session starts =======================================================================
platform win32 -- Python 3.10.1, pytest-7.2.0, pluggy-1.0.0
rootdir: E:\PyProject\pytestDemo
collected 6 items
test_scripts\test_importtoskip.py ......
============================================================================= PASSES ==============================================================================
===================================================================== short test summary info =====================================================================
PASSED test_scripts/test_importtoskip.py::test_multi[4-5-1]
PASSED test_scripts/test_importtoskip.py::test_multi[4-5-2]
PASSED test_scripts/test_importtoskip.py::test_multi[4-5-3]
PASSED test_scripts/test_importtoskip.py::test_multi[6-7-1]
PASSED test_scripts/test_importtoskip.py::test_multi[6-7-2]
PASSED test_scripts/test_importtoskip.py::test_multi[6-7-3]
======================================================================== 6 passed in 0.01s ========================================================================
实际收集到的用例是它们所有可能的组合
pytestmark 实现参数化
可以尝试通过对pytestmark复制,参数化一个测试模块
import pytest
# pytestmark: 固定写法,不是pytestmark 会报错
pytestmark = pytest.mark.parametrize('test_input,expect', [(1,2),(3,4)])
def test_one(test_input,expect):
assert test_input + 1 == expect
out:
PS E:\PyProject\pytestDemo> pytest -sv
======================================================================= test session starts =======================================================================
platform win32 -- Python 3.10.1, pytest-7.2.0, pluggy-1.0.0 -- e:\pyproject\pytestdemo\venv\scripts\python.exe
cachedir: .pytest_cache
rootdir: E:\PyProject\pytestDemo
collected 2 items
test_scripts/test_importtoskip.py::test_one[1-2] PASSED
test_scripts/test_importtoskip.py::test_one[3-4] PASSED
======================================================================== 2 passed in 0.01s ========================================================================
需要注意的是,该模块内的所有方法的入参都需要与parametrize声明的变量保持一致

argnames 参数
parametrize 方法中的第一个参数argnames 是一个用逗号分隔的字符串,或者一个元组/列表,表明指定的参数名。argnames 通常是与被标记测试方法入参的参数名
对应的,但实际上有一些限制,只能是被标记测试方法入参的子集
"""
# 源码注释:
:arg argnames: a comma-separated string denoting one or more argument
names, or a list/tuple of argument strings.
"""
argnames 覆盖同名的fixture
通常在使用fixture 和参数parametrize时,可以一个参数使用参数化,另一个参数使用fixture和参数化,而同时使用fixture和parametrize时,
parametrize 的值会覆盖原来的fixture返回的值
import pytest
@pytest.fixture()
def expected():
return 2
@pytest.fixture()
def input():
return 0
@pytest.mark.parametrize('input', [1]) # 实际取的是parametrize中的1,fixture - input 被覆盖掉
def test_sample(input, expected):
assert input + 1 == expected
执行结果:

argvalues 参数
- 参数化中参数值argvalues 是一个可迭代对象
- 如果argnams 包含多个参数,那么argvalus的迭代返回元素必须是可度量的值,即支持len()方法,并且长度和argnames所声明参数的个数相等,
所以它可以是元组/列表/集合等。
argvalues 值的来源可以是以下场景:
- Excel表中
- csv文件中
- 数据库中
"""
:arg argvalues: The list of argvalues determines how often a
test is invoked with different argument values. If only one
argname was specified argvalues is a list of values. If N
argnames were specified, argvalues must be a list of N-tuples,
where each tuple-element specifies a value for its respective
argname.
"""
使用pytest.param 为argvalues赋值
import pytest
@pytest.mark.parametrize('input, expect', [(4, 2), pytest.param(6, 3, marks=pytest.mark.xfail, id='XPASS')])
def test_sample(input, expect):
assert input / 2 == expect
运行结果:

无论argvalues 中传递的是可度量的对象还是具体的值,在源码中都会封装成一个ParameterSet对象,它是一个具名元组:`

直接使用ParameterSet看看效果如何?
import pytest
from _pytest.mark.structures import ParameterSet
@pytest.mark.parametrize('input, expect', [(4, 2), ParameterSet(values=[6,3],marks=[pytest.mark.xfail],id='XPASS')])
def test_sample(input, expect):
assert input / 2 == expect
运行结果:

成功运行,因此可以总结 pytest.param 的作用就是封装一个ParameterSet
本文来自博客园,作者:chuangzhou,转载请注明原文链接:https://www.cnblogs.com/czzz/p/15720828.html

浙公网安备 33010602011771号