当前位置:网站首页>pytest合集(7)— 参数化
pytest合集(7)— 参数化
2022-07-29 06:00:00 【笃行之.kiss】
一、pytest.mark.parametrize()
(1)语法糖:
parametrize
(argnames, argvalues, indirect=False, ids=None, scope=None, *, _param_mark=None)
(2)参数说明:
argnames:参数名,以逗号分隔的字符串,表示一个或多个参数名称。或参数字符串组成的列表/元组。
如果是一个参数,使用参数名的字符串。
如果是多个参数,多个参数名之间使用逗号分隔的字符串,或者多个参数名组成的列表,或者多个参数名组成的元组。
argvalues:参数值,类型是一个可迭代对象,和参数名一一对应。
如果argnames为一个参数,则argvalues是一个值列表。
如果argnames为多个参数,则argvalues必须是一个嵌套元组的列表,其中每个元组元素值与参数名一一对应。
indirect:参数名称列表(参数名称的子集)或布尔值。
indirect一般与Pytest的fixture,request.param组合使用
当indrect =True时,argnames参数名是fixture夹具的函数名,argvalues则是给这个夹具函数传递的参数。
ids:标记参数化测试用例的执行名称,默认自动生成,多个参数名之间用"-"连接。
scope:参数范围。
(3)源码:
def parametrize( self, argnames: Union[str, List[str], Tuple[str, ...]], argvalues: Iterable[Union[ParameterSet, Sequence[object], object]], indirect: Union[bool, Sequence[str]] = False, ids: Optional[ Union[Iterable[Optional[object]], Callable[[Any], Optional[object]]] ] = None, scope: "Optional[_ScopeName]" = None, *, _param_mark: Optional[Mark] = None, ) -> None: """Add new invocations to the underlying test function using the list of argvalues for the given argnames. Parametrization is performed during the collection phase. If you need to setup expensive resources see about setting indirect to do it rather than at test setup time. Can be called multiple times, in which case each call parametrizes all previous parametrizations, e.g. :: unparametrized: t parametrize ["x", "y"]: t[x], t[y] parametrize [1, 2]: t[x-1], t[x-2], t[y-1], t[y-2] :param argnames: A comma-separated string denoting one or more argument names, or a list/tuple of argument strings. :param 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. :param indirect: A list of arguments' names (subset of argnames) or a boolean. If True the list contains all names from the argnames. Each argvalue corresponding to an argname in this list will be passed as request.param to its respective argname fixture function so that it can perform more expensive setups during the setup phase of a test rather than at collection time. :param ids: Sequence of (or generator for) ids for ``argvalues``, or a callable to return part of the id for each argvalue. With sequences (and generators like ``itertools.count()``) the returned ids should be of type ``string``, ``int``, ``float``, ``bool``, or ``None``. They are mapped to the corresponding index in ``argvalues``. ``None`` means to use the auto-generated id. If it is a callable it will be called for each entry in ``argvalues``, and the return value is used as part of the auto-generated id for the whole set (where parts are joined with dashes ("-")). This is useful to provide more specific ids for certain items, e.g. dates. Returning ``None`` will use an auto-generated id. If no ids are provided they will be generated automatically from the argvalues. :param scope: If specified it denotes the scope of the parameters. The scope is used for grouping tests by parameter instances. It will also override any fixture-function defined scope, allowing to set a dynamic scope using test context or configuration. """
1、单个参数名
新建 test_parametrize.py 文件如下:
import pytest # 单个参数名 @pytest.mark.parametrize('a', [1, 2, 3]) def test_one(a): print(a)
运行命令:ytest test_parametrize.py -vs
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>pytest test_parametrize.py -vs
==================================== test session starts ====================================
platform win32 -- Python 3.8.8, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 -- e:\programs\python\python38\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.8.8', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '6.2.3', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'html': '3.1.1', 'metadata': '1.11.0', 'rerunfailures': '9.1.1', 'assume': '2.2.0', 'requests-mock': '1.7.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_271'}
rootdir: C:\Users\057776\PycharmProjects\pytest-demo\testmark, configfile: pytest.ini
plugins: html-3.1.1, metadata-1.11.0, rerunfailures-9.1.1, assume-2.2.0, requests-mock-1.7.0
collected 3 itemstest_parametrize.py::test_one[1] 1 PASSED
test_parametrize.py::test_one[2] 2 PASSED
test_parametrize.py::test_one[3] 3 PASSED==================================== 3 passed in 0.04s ====================================
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>
说明:
argnames参数名只有一个参数的时候,使用参数名的字符串,argvalues参数值使用一个列表。
测试用例test_one使用装饰器parametrize,pytest每次运行测试用例的时候,参数名a都会从参数值[1,2,3]中取出一个值来运行子用例。
2、多个参数名
修改 test_parametrize.py 文件如下:
import pytest # 单个参数名 @pytest.mark.parametrize('a', [1, 2, 3]) def test_one(a): print(a) # 多个参数名 @pytest.mark.parametrize("a,b", [('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')]) # @pytest.mark.parametrize(['a', 'b'], [('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')]) # @pytest.mark.parametrize(('a', 'b'), [('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')]) def test_two(a, b): print(a, b)
运行命令:pytest test_parametrize.py -vs
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>pytest test_parametrize.py -vs
=================================== test session starts ===================================
platform win32 -- Python 3.8.8, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 -- e:\programs\python\python38\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.8.8', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '6.2.3', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'html': '3.1.1', 'metadata': '1.11.0', 'rerunfailures': '9.1.1', 'assume': '2.2.0', 'requests-mock': '1.7.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_271'}
rootdir: C:\Users\057776\PycharmProjects\pytest-demo\testmark, configfile: pytest.ini
plugins: html-3.1.1, metadata-1.11.0, rerunfailures-9.1.1, assume-2.2.0, requests-mock-1.7.0
collected 6 itemstest_parametrize.py::test_one[1] 1 PASSED
test_parametrize.py::test_one[2] 2 PASSED
test_parametrize.py::test_one[3] 3 PASSED
test_parametrize.py::test_two[a1-b1] a1 b1 PASSED
test_parametrize.py::test_two[a2-b2] a2 b2 PASSEDtest_parametrize.py::test_two[a3-b3] a3 b3 PASSED
=================================== 6 passed in 0.07s ===================================
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>
说明:
argnames参数名有多个的时候,多个参数名之间使用逗号分隔的字符串,多个参数名组成的列表,多个参数名组成的元组,这三种写法都可以。
argnames参数名有多个的时候,argvalues必须是一个嵌套元组的列表,其中每个元组元素值与参数名一一对应。
ids参数,默认自动生成,多个参数名之间用"-"连接。
pytest运行的时候,parametrize装饰的测试用例test_two依次从参数值列表[('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')]中取出3个元组,运行3次测试用例。
3、indrect =True 夹具参数化
修改 test_parametrize.py 文件如下:
import pytest# 夹具参数化 @pytest.fixture() def fixture_demo(request): return request.param + 1 lst = [1, 2, 3] # indirect=True,argnames作为参数传入参数名对应的夹具函数 @pytest.mark.parametrize('fixture_demo', lst, indirect=True) def test_three(fixture_demo): print(fixture_demo)
运行命令:pytest test_parametrize.py -vs
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>pytest test_parametrize.py -vs
================================= test session starts =================================
platform win32 -- Python 3.8.8, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 -- e:\programs\python\python38\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.8.8', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '6.2.3', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'html': '3.1.
1', 'metadata': '1.11.0', 'rerunfailures': '9.1.1', 'assume': '2.2.0', 'requests-mock': '1.7.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_271'}
rootdir: C:\Users\057776\PycharmProjects\pytest-demo\testmark, configfile: pytest.ini
plugins: html-3.1.1, metadata-1.11.0, rerunfailures-9.1.1, assume-2.2.0, requests-mock-1.7.0
collected 3 itemstest_parametrize.py::test_three[1] 2 PASSED
test_parametrize.py::test_three[2] 3 PASSED
test_parametrize.py::test_three[3] 4 PASSED=================================== 3 passed in 0.05s ===================================
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>
说明:
当indrect =True时,argnames参数名是fixture夹具的函数名,argvalues则是给这个夹具函数传递值的参数。
夹具pytest.fixture(params) 可以用来实现参数化,参数化的时候这里需要用到一个参数request,用来接收fixture返回的结果,通过request.param来返回参数内容。
4、装饰测试类
修改 test_parametrize.py 文件如下:
import pytest # 装饰类需要注意参数要和类中的所有测试函数保持一致 @pytest.mark.parametrize("a,b", [('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')]) class TestClass: def test_four(self, a, b): print(a, b) def test_five(self, a, b): print(a + b)
运行命令:pytest test_parametrize.py -vs
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>pytest test_parametrize.py -vs
=================================== test session starts ===================================
platform win32 -- Python 3.8.8, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 -- e:\programs\python\python38\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.8.8', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '6.2.3', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'html': '3.1.
1', 'metadata': '1.11.0', 'rerunfailures': '9.1.1', 'assume': '2.2.0', 'requests-mock': '1.7.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_271'}
rootdir: C:\Users\057776\PycharmProjects\pytest-demo\testmark, configfile: pytest.ini
plugins: html-3.1.1, metadata-1.11.0, rerunfailures-9.1.1, assume-2.2.0, requests-mock-1.7.0
collected 6 itemstest_parametrize.py::TestClass::test_four[a1-b1] a1 b1 PASSED
test_parametrize.py::TestClass::test_four[a2-b2] a2 b2 PASSED
test_parametrize.py::TestClass::test_four[a3-b3] a3 b3 PASSED
test_parametrize.py::TestClass::test_five[a1-b1] a1b1 PASSED
test_parametrize.py::TestClass::test_five[a2-b2] a2b2 PASSED
test_parametrize.py::TestClass::test_five[a3-b3] a3b3 PASSED=================================== 6 passed in 0.20s ===================================
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>
说明:
parametrize装饰的类TestClass中的所有测试用例都调用了参数化。
5、装饰模块
修改 test_parametrize.py 文件如下:
import pytest pytestmark = pytest.mark.parametrize("a,b", [('a1', 'b1'), ('a2', 'b2'), ('a3', 'b3')]) def test_two(a, b): print(a, b) class TestClass: def test_four(self, a, b): print(a, b) def test_five(self, a, b): print(a + b)
运行命令:pytest test_parametrize.py -vs
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>pytest test_parametrize.py -vs
=================================== test session starts ===================================
platform win32 -- Python 3.8.8, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 -- e:\programs\python\python38\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.8.8', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '6.2.3', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'html': '3.1.1', 'metadata': '1.11.0', 'rerunfailures': '9.1.1', 'assume': '2.2.0', 'requests-mock': '1.7.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_271'}
rootdir: C:\Users\057776\PycharmProjects\pytest-demo\testmark, configfile: pytest.ini
plugins: html-3.1.1, metadata-1.11.0, rerunfailures-9.1.1, assume-2.2.0, requests-mock-1.7.0
collected 9 itemstest_parametrize.py::test_two[a1-b1] a1 b1 PASSED
test_parametrize.py::test_two[a2-b2] a2 b2 PASSED
test_parametrize.py::test_two[a3-b3] a3 b3 PASSED
test_parametrize.py::TestClass::test_four[a1-b1] a1 b1 PASSED
test_parametrize.py::TestClass::test_four[a2-b2] a2 b2 PASSED
test_parametrize.py::TestClass::test_four[a3-b3] a3 b3 PASSED
test_parametrize.py::TestClass::test_five[a1-b1] a1b1 PASSED
test_parametrize.py::TestClass::test_five[a2-b2] a2b2 PASSED
test_parametrize.py::TestClass::test_five[a3-b3] a3b3 PASSED==================================== 9 passed in 0.08s ====================================
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>
说明:
使用全局变量pytestmark = pytest.mark.parametrize(),可以参数化模块中的所有测试用例。
6、使用内置mark.xfail,在参数化中标记测试用例预期执行失败
修改 test_parametrize.py 文件如下:
import pytest # 使用内置mark.xfail,在参数化中标记单个测试用例预期执行失败 @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
运行命令:pytest test_parametrize.py -vs
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>pytest test_parametrize.py -v
================================== test session starts ==================================
platform win32 -- Python 3.8.8, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 -- e:\programs\python\python38\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.8.8', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '6.2.3', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'html': '3.1.1', 'metadata': '1.11.0', 'rerunfailures': '9.1.1', 'assume': '2.2.0', 'requests-mock': '1.7.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_271'}
rootdir: C:\Users\057776\PycharmProjects\pytest-demo\testmark, configfile: pytest.ini
plugins: html-3.1.1, metadata-1.11.0, rerunfailures-9.1.1, assume-2.2.0, requests-mock-1.7.0
collected 3 itemstest_parametrize.py::test_eval[3+5-8] PASSED [ 33%]
test_parametrize.py::test_eval[2+4-6] PASSED [ 66%]
test_parametrize.py::test_eval[6*9-42] XFAIL [100%]=============================== 2 passed, 1 xfailed in 0.46s ===============================
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>
说明:
xfail 标记的测试用例预期执行失败,实际执行失败,则状态标记为XFAIL。
7、堆叠多个parametrize装饰器
修改 test_parametrize.py 文件如下:
import pytest # 堆叠多个parametrize装饰器,在这种情况下,每次调用都会参数化所有先前的参数化。 @pytest.mark.parametrize('a', ['a1', 'a2']) @pytest.mark.parametrize('b', ['b1', 'b2', 'b3']) def test_over(a, b): print(a, b)
运行命令:pytest test_parametrize.py -vs
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>pytest test_parametrize.py -vs
=================================== test session starts ===================================
platform win32 -- Python 3.8.8, pytest-6.2.3, py-1.10.0, pluggy-0.13.1 -- e:\programs\python\python38\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.8.8', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '6.2.3', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'html': '3.1.1', 'metadata': '1.11.0', 'rerunfailures': '9.1.1', 'assume': '2.2.0', 'requests-mock': '1.7.0'}, 'JAVA_HOME': 'C:\\Program Files\\Java\\jdk1.8.0_271'}
rootdir: C:\Users\057776\PycharmProjects\pytest-demo\testmark, configfile: pytest.ini
plugins: html-3.1.1, metadata-1.11.0, rerunfailures-9.1.1, assume-2.2.0, requests-mock-1.7.0
collected 6 itemstest_parametrize.py::test_over[b1-a1] a1 b1 PASSED
test_parametrize.py::test_over[b1-a2] a2 b1 PASSED
test_parametrize.py::test_over[b2-a1] a1 b2 PASSED
test_parametrize.py::test_over[b2-a2] a2 b2 PASSED
test_parametrize.py::test_over[b3-a1] a1 b3 PASSED
test_parametrize.py::test_over[b3-a2] a2 b3 PASSED=================================== 6 passed in 0.07s ===================================
(venv) C:\Users\057776\PycharmProjects\pytest-demo\testmark>
说明:
堆叠多个parametrize装饰器,在这种情况下,每次调用都会参数化所有先前的参数化。
二、pytest.fixture(params)
待整理
reference:
API Reference — pytest documentation
How to parametrize fixtures and test functions — pytest documentation
边栏推荐
- 基于C语言设计的学籍管理系统
- vim文本编辑器的一些使用小技巧
- Etcd principle
- 谷歌零碎笔记之JWT(草稿)
- 吴恩达老师机器学习课程笔记 00 写在前面
- 网上传说软件测试培训真的那么黑心吗?都是骗局?
- MVFuseNet:Improving End-to-End Object Detection and Motion Forecasting through Multi-View Fusion of
- The difference between pairs and ipairs
- C language memory stack and heap usage
- 【flask入门系列】Flask-SQLAlchemy的安装与配置
猜你喜欢
Teacher Wu Enda's machine learning course notes 02 univariate linear regression
Idea cannot find a database solution
Teacher wangshuyao's notes on operations research course 10 linear programming and simplex method (discussion on detection number and degradation)
Flink实时仓库-DWD层(交易域-加购维度退化处理)模板代码
线程 - 线程安全 - 线程优化
MySql基础知识(高频面试题)
Windows 上 php 7.4 连接 oracle 配置
基于C语言设计的学籍管理系统
【论文阅读】TomoAlign: A novel approach to correcting sample motion and 3D CTF in CryoET
阿里一面,给了几条SQL,问需要执行几次树搜索操作?
随机推荐
SSH免密登录-两台虚拟机建立免密通道 双向信任
leetcode-1331:数组序号转换
吴恩达老师机器学习课程笔记 04 多元线性回归
mysql查询区分大小写
Thread - thread safety - thread optimization
模拟卷Leetcode【普通】093. 复原 IP 地址
mysql可以定时导出表格吗?
Summary of 2022 SQL classic interview questions (with analysis)
Overview of database system
【冷冻电镜】RELION4.0之subtomogram对位功能源码分析(自用)
【论文阅读 | 冷冻电镜】RELION 4.0 中新的 subtomogram averaging 方法解读
Teacher wangshuyao's notes on operations research 06 linear programming and simplex method (geometric significance)
SDN topology discovery principle
C language memory stack and heap usage
联邦学习后门攻击总结(2019-2022)
The core of openresty and cosocket
王树尧老师运筹学课程笔记 10 线性规划与单纯形法(关于检测数与退化的讨论)
数据库持久化+JDBC数据库连接
【论文阅读】TomoAlign: A novel approach to correcting sample motion and 3D CTF in CryoET
HJ37 统计每个月兔子的总数 斐波那契数列