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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!