pytest中参数化的几种方法

  • @pytest.mark.parametrize
    • 元组组成的列表进行参数化,每一组元素表示一组参数化值
    • 每个参数单独赋值
    • 添加用例id
    • pytest.param, 针对单个参数化添加mark标记或者id
    • 利用indirect参数,通过fixture实现间接参数化
  • pytest_generate_tests
    • 根据输入命令动态选择参数值
    • 执行命令动态输入参数值

@pytest.mark.parametrize

pytest.mark.parametrize可以实现参数化,它包含的参数有:

  • argnames:一个或者多各参数名,逗号分割
  • argvalues:和argnames对应,若argname只有一个值列表,那么argvalues也只有一个值,如果有n个argname,argvalues必须时n元组的列表
  • indirect:它的值是bool值或者argnames的子集;如果是True,则表示argnames中的所有名称,通过argname对应的fixture函数传递进行赋值,而不是在进行用例收集时就赋值
  • ids:每组参数的id
  • scope:指定参数范围

元组组成的列表进行参数化,每一组元素表示一组参数化值

  • 如下使用testdata值进行参数化
#content of test_param.py
#coding=utf-8
import pytesttestdata = [(3, 4, -1),(6,3, 3),
]@pytest.mark.parametrize("a,b,expected", testdata)
def test_diff_v0(a, b, expected):diff = a - bassert diff == expected
  • 执行pytest test_param.py --collect-only查看收集的用例如下:
    收集到两个用例test_diff_v0[3-4--1]test_diff_v0[6-3-3]
D:\Python\program\practic_unittest>pytest test_param.py --collect-only
============================================================================ test session starts =============================================================================
platform win32 -- Python 3.8.4, pytest-6.2.4, py-1.9.0, pluggy-0.13.1
rootdir: D:\Python\program\practic_unittest, configfile: pytest.ini
plugins: allure-pytest-2.8.16
collected 2 items                                                                                                                                                             <Module test_param.py><Function test_diff_v0[3-4--1]><Function test_diff_v0[6-3-3]>========================================================================= 2 tests collected in 0.02s =========================================================================

每个参数单独赋值

  • 根据每个元素值的个数,每个参数值组合生成一条用例
#content of test_param.py
#coding=utf-8
import pytesttestdata = [(3, 4),(6,3),
]
@pytest.mark.parametrize("expected", [-1,3])
@pytest.mark.parametrize("a,b", testdata)
def test_diff_v1(a, b, expected):diff = a - bassert diff == expected
  • 执行pytest test_param.py --collect-only查看收集的用例如下:
    收集到四(2*2)个用例test_diff_v1[3-4--1]test_diff_v1[3-4-3]test_diff_v1[6-3--1]test_diff_v1[6-3-3]
D:\Python\program\practic_unittest>pytest test_param.py --collect-only
============================================================================ test session starts =============================================================================
platform win32 -- Python 3.8.4, pytest-6.2.4, py-1.9.0, pluggy-0.13.1
rootdir: D:\Python\program\practic_unittest, configfile: pytest.ini
plugins: allure-pytest-2.8.16
collected 4 items                                                                                                                                                             <Module test_param.py><Function test_diff_v1[3-4--1]><Function test_diff_v1[3-4-3]><Function test_diff_v1[6-3--1]><Function test_diff_v1[6-3-3]>========================================================================= 4 tests collected in 0.02s ========================================================================

添加用例id

  • 通过以上的例子可以看出生成的用例名称后面跟的是参数的值,可以通过各ids或者id赋值,指定用例标识
#content of test_param.py
# coding=utf-8
import pytesttestdata = [(3, 4, -1),(6, 3, 3),
]@pytest.mark.parametrize("a,b,expected", testdata, ids=["test1", "test2"])
def test_diff_v2(a, b, expected):diff = a - bassert diff == expected
  • 执行pytest test_param.py --collect-only查看收集的用例如下:
    收集到两个用例test_diff_v2[test1]test_diff_v2[test2]
D:\Python\program\practic_unittest>pytest test_param.py --collect-only
============================================================================ test session starts =============================================================================
platform win32 -- Python 3.8.4, pytest-6.2.4, py-1.9.0, pluggy-0.13.1
rootdir: D:\Python\program\practic_unittest, configfile: pytest.ini
plugins: allure-pytest-2.8.16
collected 2 items                                                                                                                                                             <Module test_param.py><Function test_diff_v2[test1]><Function test_diff_v2[test2]>========================================================================= 2 tests collected in 0.02s =========================================================================

pytest.param, 针对单个参数化添加mark标记或者id

  • 对于添加了mark标记的,可通过-m name来执行指定用例
  • pytest.param的参数有:
    values:参数值
    marks: 参数添加mark标记,可以是单个值也可以是一个列表
    id:设置参数的id
#content of test_param.py
# coding=utf-8
import pytest#利用pytest.param添加
@pytest.mark.parametrize("a,b,expected",[(4,2,1), pytest.param(9,3,6, marks=pytest.mark.xfail,id="expect fail"),pytest.param(5,3,1,marks=[pytest.mark.first,pytest.mark.xfail],id="test3")],
)
def test_diff_v3(a, b, expected):diff = a - bassert diff == expected#content of pytest.ini
[pytest]
markers=first:mark run first
  • 执行pytest test_param.py --collect-only查看收集的用例如下:
    收集到三个用例,但是只选择了有xfail标记的test_diff_v3[expect fail]test_diff_v3[test3]
D:\Python\program\practic_unittest>pytest test_param.py --collect-only -m xfail
============================================================================ test session starts =============================================================================
platform win32 -- Python 3.8.4, pytest-6.2.4, py-1.9.0, pluggy-0.13.1
rootdir: D:\Python\program\practic_unittest, configfile: pytest.ini
plugins: allure-pytest-2.8.16
collected 3 items / 1 deselected / 2 selected                                                                                                                                 <Module test_param.py><Function test_diff_v3[expect fail]><Function test_diff_v3[test3]>================================================================ 2/3 tests collected (1 deselected) in 0.02s =================================================================

利用indirect参数,通过fixture实现间接参数化

# content of test_param.py
# coding=utf-8
import pytest@pytest.fixture(scope="function")
def x(request):return request.param * 3@pytest.fixture(scope="function")
def y(request):return request.param * 2@pytest.mark.parametrize("x, y", [("a", "b")], indirect=True)
def test_indirect(x, y):assert x == "aaa"assert y == "bb"
  • 执行pytest test_param.py用例执行通过
D:\Python\program\practic_unittest>pytest test_param.py
============================================================================ test session starts =============================================================================
platform win32 -- Python 3.8.4, pytest-6.2.4, py-1.9.0, pluggy-0.13.1
rootdir: D:\Python\program\practic_unittest, configfile: pytest.ini
plugins: allure-pytest-2.8.16
collected 1 item                                                                                                                                                              test_param.py::test_indirect[a-b] PASSED                                                                                                                                [100%]============================================================================= 1 passed in 0.02s ==============================================================================
  • 修改test_param.py中的@pytest.mark.parametrize("x, y", [("a", "b")], indirect=True)@pytest.mark.parametrize("x, y", [("a", "b")], indirect=["x"])后,执行结果是不通过,因为在断言assert y == "bb"时不通过
D:\Python\program\practic_unittest>pytest test_param.py
============================================================================ test session starts =============================================================================
platform win32 -- Python 3.8.4, pytest-6.2.4, py-1.9.0, pluggy-0.13.1
rootdir: D:\Python\program\practic_unittest, configfile: pytest.ini
plugins: allure-pytest-2.8.16
collected 1 item                                                                                                                                                              test_param.py::test_indirect[a-b] FAILED                                                                                                                                [100%]================================================================================== FAILURES ==================================================================================
_____________________________________________________________________________ test_indirect[a-b] _____________________________________________________________________________x = 'aaa', y = 'b'@pytest.mark.parametrize("x, y", [("a", "b")], indirect=["x"])def test_indirect(x, y):assert x == "aaa"
>       assert y == "bb"
E       AssertionError: assert 'b' == 'bb'
E         - bb
E         + btest_param.py:16: AssertionError
========================================================================== short test summary info ===========================================================================
FAILED test_param.py::test_indirect[a-b] - AssertionError: assert 'b' == 'bb'
============================================================================= 1 failed in 0.13s ==============================================================================

pytest_generate_tests

  • 利用pytest_generate_tests钩子可以动态确定参数或者fixture范围,通过传入的metafunc对象可以检查请求上下文,调用metafunc.parametrize()进行参数化
  • metafunc.parametrize()的参数值和pytest.mark.parametrize一样

根据输入命令动态选择参数值

比如需要在多个环境运行脚本,而每个环境的参数不一样,可通过一下方式来实现动态赋值
在conftest.py中定义

# content of test_param.py
# coding=utf-8
import pytestdef test_compute(param):assert param < 4#conftest.py
def pytest_addoption(parser):parser.addoption("--dev", action="store_true", help="run in dev env,otherwise run in test env")   #带--dev参数时默认值时true,不带时为false
# action的值store、store_const,store_true,store_false,append,append_const,count,extenddef pytest_generate_tests(metafunc):if "param" in metafunc.fixturenames:if metafunc.config.getoption("dev"):name = [1,2,3]else:name = [3,4,5]metafunc.parametrize("param", name)
  • 执行pytest test_param.py --collect-only和执行pytest test_param.py --collect-only --dev查看收集的用例如下:
    分别取name=[3,4,5]name=[1,2,3]的值
D:\Python\program\practic_unittest>pytest test_param.py --collect-only
============================================================================ test session starts =============================================================================
platform win32 -- Python 3.8.4, pytest-6.2.4, py-1.9.0, pluggy-0.13.1
rootdir: D:\Python\program\practic_unittest, configfile: pytest.ini
plugins: allure-pytest-2.8.16
collected 3 items                                                                                                                                                             <Module test_param.py><Function test_compute[3]><Function test_compute[4]><Function test_compute[5]>========================================================================= 3 tests collected in 0.02s =========================================================================D:\Python\program\practic_unittest>pytest test_param.py --collect-only --dev
============================================================================ test session starts =============================================================================
platform win32 -- Python 3.8.4, pytest-6.2.4, py-1.9.0, pluggy-0.13.1
rootdir: D:\Python\program\practic_unittest, configfile: pytest.ini
plugins: allure-pytest-2.8.16
collected 3 items                                                                                                                                                             <Module test_param.py><Function test_compute[1]><Function test_compute[2]><Function test_compute[3]>========================================================================= 3 tests collected in 0.02s =========================================================================

执行命令动态输入参数值

如下代码parser.addoption的action改为append后(更多action值地址),在执行命令时把输入的值传给参数

# content of test_param.py
# coding=utf-8
import pytestdef test_compute(param):assert param < 4#conftest.py
def pytest_addoption(parser):parser.addoption("--dev", action="apend", help="run in dev env,otherwise run in test env")   #带--dev参数时默认值时true,不带时为false
#action的值store、store_const,store_true,store_false,append,append_const,count,extenddef pytest_generate_tests(metafunc):if "param" in metafunc.fixturenames:metafunc.parametrize("param",metafunc.config.getoption("dev"))  #metafunc.config.getoption检索命令行选项的值,取到的dev值赋给param参数,metafunc.config.getini(name) 检索 ini 样式文件中读取的值
  • 执行pytest test_param.py --collect-only --dev 3或者pytest test_param.py --collect-only --dev 3 --dev 45分别收集到一条/两条用例:
    test_compute[3]test_compute[45]
D:\Python\program\practic_unittest>pytest test_param.py --collect-only --dev 3
============================================================================ test session starts =============================================================================
platform win32 -- Python 3.8.4, pytest-6.2.4, py-1.9.0, pluggy-0.13.1
rootdir: D:\Python\program\practic_unittest, configfile: pytest.ini
plugins: allure-pytest-2.8.16
collected 1 item                                                                                                                                                              <Module test_param.py><Function test_compute[3]>========================================================================= 1 test collected in 0.02s ==========================================================================D:\Python\program\practic_unittest>pytest test_param.py --collect-only --dev 3 --dev 45
============================================================================ test session starts =============================================================================
platform win32 -- Python 3.8.4, pytest-6.2.4, py-1.9.0, pluggy-0.13.1
rootdir: D:\Python\program\practic_unittest, configfile: pytest.ini
plugins: allure-pytest-2.8.16
collected 2 items                                                                                                                                                             <Module test_param.py><Function test_compute[3]><Function test_compute[45]>========================================================================= 2 tests collected in 0.03s =========================================================================

参考文档:https://docs.pytest.org/en/6.2.x/example/parametrize.html#paramexamples

pytest中参数化方法,并且根据执行的命令进行动态参数化相关推荐

  1. AutoCAD中程序创建Ribbon界面执行AutoCAD命令

    在基于AutoCAD做二次开发时,常见的教程讲的都是在DLL中定义一些自定义命令,然后通过netload命令加载这个DLL,通过执行自定义命令的方式来执行我们的自定义功能.这样的方式在在学习中是显得很 ...

  2. linux中利用shell脚本条件执行linux命令

    linux中利用shell脚本条件执行命令 在linux环境中,我们总会有一些命令需要经常用,例如经常跳转到某些目录下或者执行某些命令,输入一连串的命令是很烦的,此时我们可以预先写一些脚本然后根据我们 ...

  3. android中 onResume()方法什么时候执行 ??(转)

    转自: onResume是在启动activity启动之后才能执行的,也就是恢复执行.程序正常启动:onCreate()->onStart()->onResume(); 正常退出:onPau ...

  4. 【pytest】Hook 方法之 pytest_addoption :注册命令行参数

    Hook 方法之 pytest_addoption : pytest_addoption 可以让用户注册一个自定义的命令行参数,方便用户将数据传递给 pytest: 这个 Hook 方法一般和 内置 ...

  5. Hystrix的一个坑,queue中的run方法没有被执行?

    今天学的时候随手测了一下Hystrix的queue的异步执行,发现执行queue之后,还没有打印run方法中的内容,程序就结束了: import com.netflix.hystrix.Hystrix ...

  6. 【面向对象编程】(4) 类的继承,重构父类中的方法

    各位同学好,今天和大家分享一下面向对象编程中,类的三大特征之继承.主要介绍:子类继承父类的基本方法:重写父类的类方法:重构父类的初始化方法:super() 方法.本节主要是单继承,多继承在下一节中介绍 ...

  7. java 执行外部命令 苹果_Java中执行外部命令

    在项目中执行一个linux的shell脚本,于是需要在java环境下执行外部命令如系统命令.linux命令的需求,本人小小研究了一下,又上网查了一些资料先整理如下. java执行外部命令主要依赖两个类 ...

  8. python 执行shell_python学习——python中执行shell命令

    这里介绍一下python执行shell命令的四种方法: 1.os模块中的os.system()这个函数来执行shell命令>>> os.system('ls') anaconda-k ...

  9. 纠正英文句子的拼写错误textblob模块中correct方法

    [小白从小学Python.C.Java] [等级考试+500强双证书+考研] [Python-数据分析] 纠正英文句子的拼写错误 textblob模块中correct方法 选择题 以下执行结果正确的是 ...

最新文章

  1. C++ STL标准模板库(stack)
  2. 小程序离成功还差一个版本
  3. SpringBoot打包时提示:Perhaps you are running on a JRE rather than a JDK?
  4. SNF平台从sql server兼容oracle的处理方式和开发方式
  5. mysql安装后变10g_Oracle 10G安装中一些常见问题解决
  6. 【flink】flink作业超额启动多个taskManager k8s
  7. java之NIO简介
  8. 计算机特殊的标点符号教案,《标点符号的输入》教学设计
  9. xftp7要继续使用此程序,您必须应用最新的更新,100%已解决.
  10. 基于U3D的VR开发教程:(1)基础环境配置
  11. 题目59 考勤记录(ok)
  12. Echarts桑基图sankey点击高亮显示
  13. Mac上备份iphone照片
  14. 【Java并发编程】闭锁
  15. SonicWall防火墙销量超300万套,合作伙伴项目报备量增长50%,
  16. 【解决】小程序|微信公众号授权给第三方平台时报“没有绑定公众号”
  17. 该如何把小程序安装成APP?
  18. 基于HTML实现的装饰品电商App模板(含源码)
  19. 随手记:CentOS7 下 Docker 中 MySQL5.7 挂载宿主目录无权限
  20. 微服务系列笔记之什么是微服务

热门文章

  1. 古风尚婚纱摄影--决定
  2. 传统民俗闹新春 浙江千年古村飘“非遗年味”
  3. 【R1CS to QAP】
  4. Hadoop小兵笔记【六】hadoop2.2.0伪分布式环境搭建疑难-JobHistory显示Job信息为空
  5. 如何展示实时音视频通话时正在说话用户的音浪
  6. 申论中关于人物“精神”、“品质”的总结
  7. 你值得安装的24个chrome插件!!!
  8. “集成电路”“国家安全学”正式成为一级学科!
  9. 索引顺序查找(分块查找)
  10. 51单片机 引脚功能定义,内部框图