在 Python 中动态参数化多个测试

2024-02-20

我正在尝试使用 Pytest 编写动态测试套件,其中测试数据保存在单独的文件中,例如YAML 文件或 .csv。我想运行多个测试,所有这些测试都是从同一个文件进行参数化的。假设我有一个测试文件test_foo.py,看起来像这样:

import pytest

@pytest.mark.parametrize("num1, num2, output", ([2, 2, 4], [3, 7, 10], [48, 52, 100]))
def test_addnums(num1, num2, output):
    assert foo.addnums(num1, num2) == output

@pytest.mark.parametrize("foo, bar", ([1, 2], ['moo', 'mar'], [0.5, 3.14]))
def test_foobar(foo, bar):
    assert type(foo) == type(bar)

使用参数化装饰器,我可以在 pytest 中运行多个测试,并且按预期工作:

test_foo.py::test_addnums[2-2-4] PASSED                                                                                                                                                            
test_foo.py::test_addnums[3-7-10] PASSED                                                                                                                                                           
test_foo.py::test_addnums[48-52-100] PASSED                                                                                                                                                        
test_foo.py::test_foobar[1-2] PASSED                                                                                                                                                               
test_foo.py::test_foobar[moo-mar] PASSED                                                                                                                                                           
test_foo.py::test_foobar[0.5-3.14] PASSED

但我想动态地参数化这些测试。我的意思是,我想编写测试数据所有测试在一个单独的文件中,以便当我运行 pytest 时,它将应用我写入每个测试函数的所有测试数据。假设我有一个类似于以下内容的 YAML 文件:

test_addnums:
  params: [num1, num2, output]
  values:
    - [2, 2, 4]
    - [3, 7, 10]
    - [48, 52, 100]

test_foobar:
  params: [foo, bar]
  values:
    - [1, 2]
    - [moo, mar]
    - [0.5, 3.14]

然后,我想要读取此 YAML 文件并使用该数据来参数化测试文件中的所有测试函数。

我知道pytest_generate_tests钩子,我一直在尝试使用它来动态加载测试。我尝试添加之前传递到的相同参数和数据值parametrize装饰器进入metafunc.parametrize hook:

def pytest_generate_tests(metafunc):
    metafunc.parametrize("num1, num2, output", ([2, 2, 4], [3, 7, 10], [48, 52, 100]))
    metafunc.parametrize("foo, bar", ([1, 2], ['moo', 'mar'], [0.5, 3.14]))

def test_addnums(num1, num2, output):
    assert foo.addnums(num1, num2) == output

def test_foobar(foo, bar):
    assert type(foo) == type(bar)

然而,这不起作用,因为 pytest 尝试将测试数据应用于每个函数:

collected 0 items / 1 error                                           

=============================== ERRORS ================================
____________________ ERROR collecting test_foo.py _____________________
In test_addnums: function uses no argument 'foo'
======================= short test summary info =======================
ERROR test_foo.py
!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!
========================== 1 error in 0.16s ===========================

我想知道的是:如何动态参数化多次测试使用pytest?我使用 pdb 内省了 pytest,据我所知,metafunc只知道您在文件中定义的第一个测试。在我上面的例子中,test_addnums首先定义,所以当我打印时vars(metafunc)在 pdb 调试器中,它显示这些值:

(Pdb) pp vars(metafunc)
{'_arg2fixturedefs': {},
 '_calls': [<_pytest.python.CallSpec2 object at 0x7f4330b6e860>,
            <_pytest.python.CallSpec2 object at 0x7f4330b6e0b8>,
            <_pytest.python.CallSpec2 object at 0x7f4330b6e908>],
 'cls': None,
 'config': <_pytest.config.Config object at 0x7f43310dbdd8>,
 'definition': <FunctionDefinition test_addnums>,
 'fixturenames': ['num1', 'num2', 'output'],
 'function': <function test_addnums at 0x7f4330b5a6a8>,
 'module': <module 'test_foo' from '<PATH>/test_foo.py'>}

但如果我换个方向test_foobar and test_addnums函数,并颠倒顺序parametrize调用,它显示有关的信息test_foobar反而。

(Pdb) pp vars(metafunc)
{'_arg2fixturedefs': {},
 '_calls': [<_pytest.python.CallSpec2 object at 0x7f6d20d5e828>,
            <_pytest.python.CallSpec2 object at 0x7f6d20d5e860>,
            <_pytest.python.CallSpec2 object at 0x7f6d20d5e898>],
 'cls': None,
 'config': <_pytest.config.Config object at 0x7f6d212cbd68>,
 'definition': <FunctionDefinition test_foobar>,
 'fixturenames': ['foo', 'bar'],
 'function': <function test_foobar at 0x7f6d20d4a6a8>,
 'module': <module 'test_foo' from '<PATH>/test_foo.py'>}

所以看起来 metafunc 实际上并没有在我的测试文件中存储有关每个测试函数的信息。因此我不能使用fixturenames or function属性,因为它们仅适用于一个特定函数,而不是所有函数。

如果是这种情况,那么我如何访问所有其他测试函数并单独参数化它们?


您可以使用以下方法执行此操作pytest_generate_tests,正如您所尝试的那样,您只需为每个函数选择正确的参数进行参数化(为了简单起见,我将解析 yaml 的结果放入全局字典中):

all_params = {
    "test_addnums": {
        "params": ["num1", "num2", "output"],
        "values":
            [
                [2, 2, 4],
                [3, 7, 10],
                [48, 52, 100]
            ]
    },
    "test_foobar":
        {
            "params": ["foo", "bar"],
            "values": [
                [1, 2],
                ["moo", "mar"],
                [0.5, 3.14]
            ]
        }
}


def pytest_generate_tests(metafunc):
    fct_name = metafunc.function.__name__
    if fct_name in all_params:
        params = all_params[fct_name]
        metafunc.parametrize(params["params"], params["values"])


def test_addnums(num1, num2, output):
    assert num1 + num2 == output


def test_foobar(foo, bar):
    assert type(foo) == type(bar)

这是相关的输出:

$python -m pytest -v param_multiple_tests.py
...
collected 6 items

param_multiple_tests.py::test_addnums[2-2-4] PASSED
param_multiple_tests.py::test_addnums[3-7-10] PASSED
param_multiple_tests.py::test_addnums[48-52-100] PASSED
param_multiple_tests.py::test_foobar[1-2] PASSED
param_multiple_tests.py::test_foobar[moo-mar] PASSED
param_multiple_tests.py::test_foobar[0.5-3.14] PASSED
===================== 6 passed in 0.27s =======================

我认为您在文档中错过的是pytest_generate_tests分别调用每个测试。更常见的使用方法是检查夹具名称而不是测试名称,例如:

def pytest_generate_tests(metafunc):
    if "foo" in metafunc.fixturenames and "bar" in metafunc.fixturenames:
         metafunc.parametrize(["foo", "bar"], ...)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Python 中动态参数化多个测试 的相关文章

  • 如何从数据库模式自动生成示例 Django 应用程序?

    我正在评估概念验证应用程序的框架 该应用程序的生命周期约为 30 天 之后它将被遗忘或完全重写 我已确定要从现有数据库模式自动生成示例应用程序 然后调整视觉设计的某些方面 我看过一个演示红宝石 on Rails 它会为数据库中的每个表自动生
  • Pyjnius导入jar文件

    Pyjnius 允许您为 java 类创建 python 包装器 例如 Hardware autoclass org myapp Hardware 有没有办法像这样导入现有的 jar 文件 语法是什么样的 您可以将 jar 添加到 CLAS
  • Django 和 AWS 简单电子邮件服务 [重复]

    这个问题在这里已经有答案了 我正在尝试启动并运行 django 站点 并且正在尝试启用 django 的标准密码重置服务 我的网站由 AWS EC2 托管 因此我想将 AWS SES 用于我的电子邮件服务 但是 我无法使 smtp 连接正常
  • 将元组列表转换为字符串 Python

    例如 我用 python 编写了一个返回列表的函数 1 1 2 2 3 3 但我希望输出为字符串 这样我就可以用另一个字符替换逗号 这样输出就是 1 1 2 2 3 3 有什么简单的方法可以解决这个问题吗 感谢您提前提供任何提示 这看起来像
  • PRAW 出现 SSLError?

    我正在尝试开始使用 PRAW 但在使用 login 时遇到问题 我有以下代码 import praw r praw Reddit This is a test bot r login myRedditUsername password 我收
  • 将Python嵌入到C中——导入模块

    我在使用嵌入式 Python for C 时遇到问题文档 http docs python org extending embedding html 每当我尝试使用导入的模块时 我都会得到 PythonIncl exe 中 0x1e089e
  • 使用 mechanize 和 beautiful soup 在 python 中进行原始 HTML 与 DOM 抓取

    我正在尝试编写一个程序 作为示例 该程序将从该网页上刮掉最高价格 http www kayak com flights JFK PAR 2012 06 01 2012 07 01 1adults http www kayak com fli
  • 如何在Python中比较列表列表中的元素以及比较列表列表中的键?

    我有以下顺序 seq ATG ATG ATG ATG GAC GAT GAA CCT GCC GCG GCA GCT 这是一个字典键 用于存储每个密码子的氨基酸值 三联碱基 例如ATG GCT etc aminoacid TTT F TTC
  • Web 应用程序框架:C++ 与 Python

    作为一名程序员 我熟悉 Python 和 C 我正在考虑编写自己的简单 Web 应用程序 并且想知道哪种语言更适合服务器端 Web 开发 我正在寻找一些东西 它必须是直观的 我认识到 Wt 存在并且它遵循 Qt 的模型 我讨厌 Qt 的一件
  • 提取二值图像中的最中心区域

    我正在处理二进制图像 之前使用此代码来查找二进制图像中的最大区域 Use the hue value to convert to binary thresh 20 thresh thresh img cv2 threshold h thre
  • Odoo:如何覆盖原始功能

    在 Odoo 中 每次打开产品表单时都会计算产品的数量 这发生在模型中product product gt function product available 该函数返回一个名为 res 的字典 Example res 8 qty ava
  • Python 日志记录 - 如何检查记录器是否为空

    我刚刚在我的应用程序中实现了日志记录 我想知道是否有一种方法可以检查记录器是否为空 我的想法是在我的脚本中设置两个处理程序 一个用于带水平仪的控制台WARNING 一个用于带级别的文件DEBUG 在脚本的最后 我需要检查是否CONSOLE记
  • Python:使用Excel CSV文件仅读取某些列和行

    虽然我可以读取 csv 文件而不是读取整个文件 但如何仅打印某些行和列 想象一下这是 Excel A B C D E State Heart Disease Rate Stroke Death Rate HIV Diagnosis Rate
  • 从 Cython 代码生成 SIMD 指令

    我需要概述在高性能数字代码中使用 Cython 可以获得的性能 我感兴趣的事情之一是找出优化的 C 编译器是否可以对 Cython 生成的代码进行矢量化 所以我决定写下面的小例子 import numpy as np cimport num
  • 在 CSV 文件的最上面一行写入

    我有这个sample csv 文件 a 1 apple b 2 banana c 3 cranberry d 4 durian e 5 eggplant 并有以下代码 samplefile open sample csv rb rows s
  • 无法从源 pylance 解析导入烧瓶

    我正在学习 Python 课程的一部分是使用 Flask 设置网络服务器 我按照 Flask 安装文档执行了步骤 由于某种原因 flask 模块带有下划线 如下所示 当我将鼠标悬停时 我会得到如下附加信息 无法从源 pylance 解析导入
  • 按键合并的两个字典的值的并集

    我有两本词典 d1 a x y b k l d2 a m n c p r 如何合并这两个字典以获得这样的结果 d3 a x y m n b k l c p r 当字典的值是简单类型 如 int 或 str 时 这有效 d3 dict i a
  • 为什么函数会修改列表以及如何防止它发生?

    我正在 Python 3 7 x 中调用一个函数并向其传递一个列表 我愿意not希望修改列表 在函数内部 我复制了列表并对其进行修改 函数完成后 传递给函数的原始列表已被修改 为什么会发生这种情况 我该如何预防 这是代码 def appen
  • 编写 CherryPy 装饰器以进行授权

    我有一个cherrypy应用程序 在某些视图上我想开始只允许某些用户查看它们 并将其他任何人发送到需要授权的页面 有没有办法使用自定义装饰器来做到这一点 我认为这将是最优雅的选择 这是我想做的一个基本示例 class MyApp autho
  • centos上无法安装Pillow

    我上面有 centos 6 3 和 python 2 6 当我尝试通过 easy install 安装它时 出现以下错误 imaging c 76 20 error Python h No such file or directory In

随机推荐

  • CSS相对位置/正常位置问题

    根据w3schools 相对位置值定义如下 relative 元素相对于其正常位置定位 因此 left 20 向元素的 LEFT 位置添加 20 个像素 我知道我可以获得相对定位的任何 DOM 对象 并使用它 我可以获得相对于原点的左侧或顶
  • VBA 宏将返回连续的月末

    这是我在这个网站上的第一篇文章 我需要有关一些 VBA 代码的帮助 该代码会将 31 07 00 放入单元格 B2 中 然后将每个月末日期放入该列中 并停止在单元格 B126 中的 31 11 2010 即单元格 B2 31 07 00 B
  • 当我上传 .png 图标时,“Android Asset Studio”会添加额外的空间,但当它使用其内部剪贴画时则不会。为什么?

    我正在尝试为我正在处理的一些 Android 应用程序创建一些漂亮的图标 有人引导我使用 Android Asset Studio 这是一个不错的在线工具 它可以创建完整的图标包 准备部署到我的 可怕的 碎片化的 Android 项目 re
  • 从中间向外循环数组的算法?

    我正在研究一种分而治之的算法 事实上 这是一种对多个输入点进行曲线拟合的算法 对于 划分 部分 我需要计算每个点的误差项 如果误差超过给定阈值 我希望在该点分割曲线并分别处理输入的左右部分 一个简单的循环就可以解决问题 但从当前部分的中间开
  • Payara5 服务器将无法部署:未知协议 RFB

    在干净的 eclipse 环境中 payara5 将不会部署 我已经使用 java 1 8 下载了正确版本的服务器 只需将其添加到新服务器即可启动它 我无法摆脱这个错误 payara 登陆页面可以工作 但管理控制台超时 任何帮助表示赞赏 2
  • 如何将正在运行的应用程序扩展到PCR中?

    如何将正在运行的应用程序扩展到PCR中 以及哪种 PCR 可以用于此目的 我假设您指的是 PC 平台上的 TPM 版本 1 2 因此您对以下规范文档感兴趣 TPM 主要部分 2 TPM 结构 http www trustedcomputin
  • 使用 .NET 实时读取文件中的更改

    我有一个经常更新的 csv 文件 大约每分钟 20 到 30 次 我想将新添加的行写入文件后立即将其插入数据库 The 文件系统观察者 http msdn microsoft com en us library system io file
  • Mac“find”和Linux“find”之间的区别[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我继承了一个脚本作为应用程序构建过程的一部分 当我在构建服务器 Ubuntu Precise 上运行它时 它运行良好 但是当我在我的 ma
  • 如何通过 RSA 生成唯一的公钥和私钥

    我正在构建一个自定义购物车 其中 CC 编号和到期日期将存储在数据库中直至处理 然后删除 我需要加密这些数据 显然 我想使用 RSACryptoServiceProvider 类 这是我创建密钥的代码 public static void
  • 用于转换许多元素的 dec2bin 函数的更快版本?

    我正在读取位图文件并进行转换each范围从 0 到 255 的 RGB 值的二进制 因此 240 x 320 位图将有 230400 个 RGB 值需要转换 原来的 dec2bin 函数太慢了 所以我编写了自己的函数 因为我知道我的值始终在
  • 没有名为 main 的模块,wkhtmltopdf 问题

    我是Python新手 但我发现的所有搜索结果对我来说都没用 C Users Aero gt pip install wkhtmltopdf Collecting wkhtmltopdf Using cached wkhtmltopdf 0
  • 如何将自定义 HTTP 标头注入 SuperAgent 发出的每个请求中?

    Clearly 超级特工 https visionmedia github io superagent 支持自定义 HTTP 标头 request post api pet send name Manny species cat set X
  • ScrollView 中的 Xamarin Center StackLayout

    我正在尝试水平居中StackLayout在一个ScrollView 但是 那StackLayout不是水平居中 它左对齐 我尝试将ScrollView但整个视图是不可滚动的 只有中心部分是可滚动的
  • Typescript用户定义的类型保护检查对象具有数组中的所有属性

    我正在尝试写一个用户定义的类型保护 https www typescriptlang org docs handbook advanced types html user defined type guards测试给定的值是否具有给定数组中
  • 我们可以在postman中读取excel中的数据进行js测试吗?

    我们可以在postman中读取excel中的数据进行js测试吗 或者 我们可以编写一个从 excel csv notepad 读取数据的 js 脚本吗 我写了一些 js 脚本来自动化我的 API 测试 我正在使用 Newman 从命令提示符
  • C# 文件处理:在可执行文件存在的目录中创建文件

    我正在创建一个独立的应用程序 该应用程序将分发给许多用户 现在 每个人都可以将可执行文件放置在其计算机上的不同位置 我希望在执行可执行文件的目录中创建一个新文件 因此 如果用户的可执行文件位于 C exefile 该文件是在那里创建的 但是
  • 如何更改 Fluent NHibernate 中小数的默认比例和精度?

    在我正在构建的应用程序中 我有许多具有特定精度和小数位数的小数字段 需要从数据库进行映射 我可以通过使用来实现这一点Precision and Scale 方法 public class ClassAMap ClassMap
  • Unity UI 中图像模糊或像素化

    我有一个 211x211 的图像 其设置如下 在我的统一用户界面中 它看起来模糊 像素化 我的统一图像宽度高度设置为 40x40 我做错了什么 即使我尝试过 2048x2048 图像 但仍然得到相同的模糊效果 图像不清楚 这是我的游戏视图
  • JSoup 不会获取所有项目?

    因此 我尝试使用 JSoup 解析一个简单的列表 不幸的是 程序仅返回列表中以 N 开头的条目之前的条目 我不知道为什么会这样 这是我的代码 public ArrayList
  • 在 Python 中动态参数化多个测试

    我正在尝试使用 Pytest 编写动态测试套件 其中测试数据保存在单独的文件中 例如YAML 文件或 csv 我想运行多个测试 所有这些测试都是从同一个文件进行参数化的 假设我有一个测试文件test foo py 看起来像这样 import