Pytest 高级用法:间接参数化

news2025/1/3 20:54:29

文章目录

    • 1. 引言
    • 2. 基础概念
      • 2.1 Fixture
      • 2.2 参数化
    • 3. 代码实例
      • 3.1 基础设置
      • 3.2 测试用例示例
        • 示例 1:基础的间接参数化
        • 示例 2:通过 request 获取参数值
        • 示例 3:多参数组合测试
        • 示例 4:部分间接参数化
    • 4. 最佳实践
    • 5. 总结
    • 参考资料

1. 引言

在进行单元测试时,我们经常需要使用不同的参数来测试同一个功能。Pytest 提供了强大的参数化功能,并且可以与 fixture 结合使用,使得测试代码更加灵活和可维护。本文将深入探讨 pytest 中参数化和 fixture 的高级用法。

2. 基础概念

2.1 Fixture

Fixture 是 pytest 中的一个核心概念,它提供了一种方式来为测试提供可复用的依赖。Fixture 可以:

  • 提供测试数据
  • 设置测试环境
  • 处理测试资源的创建和清理

2.2 参数化

参数化允许我们使用不同的参数多次运行同一个测试。pytest 提供了两种主要的参数化方式:

  • 直接参数化:参数直接传递给测试函数
  • 间接参数化:参数通过 fixture 传递给测试函数

3. 代码实例

3.1 基础设置

首先,我们需要创建两个文件:conftest.pytest_fixture_indirect.py

# conftest.py
import pytest

@pytest.fixture(scope='module')
def fixture_indirect(request):
    print(f"fixture_indirect, request: {request}")
    print(f"fixture_indirect, request.param: {request.param}")
    var = 'var_from_fixture_indirect'
    yield var

@pytest.fixture(scope='module')
def fixture_direct(request):  # request 参数可选
    print(f"fixture_direct, request: {request}")
    var = 'var_from_fixture_direct'
    yield var

3.2 测试用例示例

示例 1:基础的间接参数化
  • 使用 indirect=True 表示参数会传递给同名的 fixture
  • fixture 会接收到参数值,但测试函数只能获得 fixture 的返回值
@pytest.mark.parametrize("fixture_indirect", [110, 120], indirect=True)
def test_fixture_indirect(fixture_indirect):
    print(f"Case fixture_indirect: {fixture_indirect}")
    # 注意:这里无法直接访问参数值 110, 120

"""
会运行两次测试,每次:
- 先执行 fixture_indirect,获得参数 110/120
- 然后运行测试函数,得到 fixture 的返回值
"""
fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect[110]>>
fixture_indirect, request.param: 110
PASSED          [ 50%]
Case fixture_indirect: var_from_fixture_indirect

fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect[120]>>
fixture_indirect, request.param: 120
PASSED          [100%]
Case fixture_indirect: var_from_fixture_indirect
示例 2:通过 request 获取参数值
  • 通过 request 参数获取原始的参数化值
  • 使用 request.node.callspec.params 访问参数字典
@pytest.mark.parametrize("fixture_indirect", [110, 120], indirect=True)
def test_fixture_indirect_request(fixture_indirect, request):
    print(f"Case fixture_indirect: {fixture_indirect}")
    my_test_param = request.node.callspec.params['fixture_indirect']
    print(f"Case request.param: {my_test_param}")

"""
除了基本功能外,还能获取原始参数:
- fixture 的返回值: var_from_fixture_indirect
- 原始参数值: 110/120
"""
fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect_request[110]>>
fixture_indirect, request.param: 110
PASSED  [ 50%]
Case fixture_indirect: var_from_fixture_indirect
Case request.param: 110

fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect_request[120]>>
fixture_indirect, request.param: 120
PASSED  [100%]
Case fixture_indirect: var_from_fixture_indirect
Case request.param: 120
示例 3:多参数组合测试
  • 如何组合多个参数化装饰器
  • 直接参数化和间接参数化的混合使用
@pytest.mark.parametrize("fixture_indirect", [111, 222], indirect=True)
@pytest.mark.parametrize("test_param", ['a', 'b'])
def test_fixture_param(fixture_indirect, test_param):
    print(f"fixture_indirect: {fixture_indirect}")
    print(f"test_param: {test_param}")

"""
会生成 4 个测试用例组合:
(111, 'a')
(111, 'b')
(222, 'a')
(222, 'b')
"""
fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_param[a-111]>>
fixture_indirect, request.param: 111
PASSED           [ 25%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: a
PASSED           [ 50%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: b

fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_param[a-222]>>
fixture_indirect, request.param: 222
PASSED           [ 75%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: a
PASSED           [100%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: b
示例 4:部分间接参数化
  • 如何在一个参数化中同时使用直接和间接参数
  • 使用 indirect 列表指定哪些参数是间接的
@pytest.mark.parametrize("fixture_indirect, my_test_param",
                         [(111, 'a'), (222, 'b')],
                         indirect=['fixture_indirect'])
def test_fixture_indirect_param_partial(fixture_indirect, my_test_param):
    print(f"Case fixture_indirect: {fixture_indirect}")
    print(f"Case test_param: {my_test_param}")

"""
会生成 2 个测试用例:
(111, 'a')
(222, 'b')
"""
fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect_param_partial[111-a]>>
fixture_indirect, request.param: 111
PASSED [ 50%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: a

fixture_indirect, request: <SubRequest 'fixture_indirect' for <Function test_fixture_indirect_param_partial[222-b]>>
fixture_indirect, request.param: 222
PASSED [100%]
Case fixture_indirect: var_from_fixture_indirect
Case test_param: b

4. 最佳实践

  1. 选择合适的参数化方式

    • 简单参数使用直接参数化
    • 需要预处理或者复杂设置的参数使用间接参数化
  2. 合理使用 scope

    • 对于耗时的 fixture,使用更大的 scope(如 module)可以提高测试效率
    • 注意 scope 对测试隔离的影响
  3. 参数化组织建议

    • 相关的参数组合放在一起
    • 使用有意义的参数名
    • 考虑测试的可读性和维护性

5. 总结

Pytest 的参数化和 fixture 功能为我们提供了强大而灵活的测试工具:

  1. 灵活性:可以根据需要选择直接或间接参数化
  2. 可复用性:fixture 机制支持测试代码的重用
  3. 可维护性:通过合理组织参数和 fixture,使测试代码更易维护
  4. 效率:支持多种方式组合参数,提高测试效率

掌握这些高级用法,可以帮助我们写出更好的测试代码,提高测试效率和代码质量。

参考资料

  • Pytest 官方文档
  • Pytest Fixture 文档
  • Pytest Parametrize 文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2268988.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML——45.单元格合并

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>表格</title></head><body><!--合并单元格&#xff1a;1.在代码中找到要合并的单元格2.在要合并的所有单元格中&#xff0c;保留要合并的第一个单元格…

记录第一次跑YOLOV8做目标检测

今天是24年的最后一天&#xff0c;终于要向新世界开始破门了&#xff0c;开始深度学习&#xff0c;YOLO来敲门~ 最近做了一些皮肤检测的功能&#xff0c;在传统的处理中经历了反复挣扎&#xff0c;终于要上YOLO了。听过、看过&#xff0c;不如上手体会过~ 1、YOLO是什么&#x…

如何配置Java应用程序的远程调试

配置Java应用程序的远程调试涉及几个步骤&#xff0c;包括在启动Java应用程序时设置特定的JVM参数&#xff0c;以及在IDE&#xff08;如Eclipse、IntelliJ IDEA等&#xff09;中配置远程调试连接。以下是详细的步骤&#xff1a; 启动Java应用程序时启用远程调试 为了能够远程…

2025考研江南大学复试科目控制综合(初试807自动控制原理)

​ 2025年全国硕士研究生招生考试江南大学考点 一年年的考研如期而至&#xff0c;我也变成了研二了&#xff0c;作为2次考研经历的学长&#xff0c;总是情不自禁地回想起自己的考研经历&#xff0c;我也会经常从那段经历中汲取力量。我能理解大多数考生考完后的的迷茫无助&…

时间序列预测算法---LSTM

文章目录 一、前言1.1、深度学习时间序列一般是几维数据&#xff1f;每个维度的名字是什么&#xff1f;通常代表什么含义&#xff1f;1.2、为什么机器学习/深度学习算法无法处理时间序列数据?1.3、RNN(循环神经网络)处理时间序列数据的思路&#xff1f;1.4、RNN存在哪些问题?…

[羊城杯 2024]不一样的数据库_2

题目描述&#xff1a; 压缩包6 (1).zip需要解压密码&#xff1a; 尝试用ARCHPR工具爆破一下&#xff1a; &#xff08;字典可自行在github上查找&#xff09; 解压密码为&#xff1a;753951 解压得到13.png和Kee.kdbx文件&#xff1a; 二维码图片看上去只缺了正常的三个角&…

图像处理-Ch7-小波函数

个人博客&#xff01;无广告观看&#xff0c;因为这节内容太多了&#xff0c;有点放不下&#xff0c;分了三节 文章目录 多分辨率展开(Multi-resolution Expansions)序列展开(Series Expansions)尺度函数(Scaling Function)例&#xff1a;哈尔尺度函数(Haar scaling func)多分…

CPT203 Software Engineering 软件工程 Pt.2 敏捷方法和需求工程(中英双语)

文章目录 3. Aglie methods&#xff08;敏捷方法&#xff09;3.1 Aglie methods&#xff08;敏捷方法&#xff09;3.1.1 特点3.1.2 优点3.1.3 缺点3.1.4 原则3.1.5 计划驱动与敏捷方法的对比 3.2 Scrum3.2.1 Scrum roles3.2.2 Scrum Activities and Artifacts3.2.2.1 Product B…

【人工智能机器学习基础篇】——深入详解深度学习之神经网络基础:理解前馈神经网络与反向传播算法

深入详解深度学习之神经网络基础&#xff1a;理解前馈神经网络与反向传播算法 深度学习作为人工智能&#xff08;AI&#xff09;的核心技术&#xff0c;已经在语音识别、图像处理、自然语言处理等诸多领域取得了显著的成果。而在深度学习的众多模型中&#xff0c;**前馈神经网络…

【循环神经网络】RNN介绍

在人工神经网络中&#xff0c;”浅层网络”是指具有一个输入层、一个输出层和最多一个没有循环连接的隐藏层的网络。随着层数的增加&#xff0c;网络的复杂性也在增加。更多的层或循环连接通常会增加网络的深度&#xff0c;并使其能够提供不同级别的数据表示和特征提取&#xf…

【论文投稿】Python 网络爬虫:探秘网页数据抓取的奇妙世界

【IEEE出版|广东工业大学主办】第五届神经网络、信息与通信工程国际学术会议&#xff08;NNICE 2025&#xff09;_艾思科蓝_学术一站式服务平台 目录 前言 一、Python—— 网络爬虫的绝佳拍档 二、网络爬虫基础&#xff1a;揭开神秘面纱 &#xff08;一&#xff09;工作原…

基于深度学习的视觉检测小项目(二) 环境和框架搭建

一、环境和框架要求 SAM的环境要求&#xff1a; Python>3.7 PyTorch>1.7 torchvision>0.8 YOLO V8的环境要求&#xff1a;YOLO集成在ultralytics库中&#xff0c;ultralytics库的环境要求&#xff1a; Python>3.7 PyTorch>1.10.0 1、确定pytorch版本…

SQLiteDataBase数据库

XML界面设计 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"android:layout_width"match_paren…

cesium小知识: 处理动画的5种方式

在 Cesium 中处理动画可以通过多种方式实现,具体取决于你想要创建的动画类型。Cesium 提供了丰富的API来支持不同种类的动画,包括但不限于物体的移动、旋转、缩放、属性变化等。以下是几种常见的动画处理方法: 1. 使用 Entity 和 SampledProperty 对于动态数据或随时间变化…

【鸿蒙NEXT】鸿蒙里面类似iOS的Keychain——关键资产(@ohos.security.asset)实现设备唯一标识

前言 在iOS开发中Keychain 是一个非常安全的存储系统&#xff0c;用于保存敏感信息&#xff0c;如密码、证书、密钥等。与 NSUserDefaults 或文件系统不同&#xff0c;Keychain 提供了更高的安全性&#xff0c;因为它对数据进行了加密&#xff0c;并且只有经过授权的应用程序才…

visual studio连接sql server数据库

目录 1、为什么要建立连接2、在sql server中建立数据库3、visual studio连接sql server数据库4、学生信息管理系统页面布局5、添加事件逻辑 5.1 页面跳转5.2 读取学生信息5.3 查询学生信息5.4 修改学生信息5.5 删除学生信息5.6 添加学生信息 bilibili演示视频 github源码 1、…

STM32-笔记23-超声波传感器HC-SR04

一、简介 HC-SR04 工作参数&#xff1a; • 探测距离&#xff1a;2~600cm • 探测精度&#xff1a;0.1cm1% • 感应角度&#xff1a;<15 • 输出方式&#xff1a;GPIO • 工作电压&#xff1a;DC 3~5.5V • 工作电流&#xff1a;5.3mA • 工作温度&#xff1a;-40~85℃ 怎么…

vuex - 第一天

思维逻辑 解决问题 代码能力2 vue2的项目 北京前端鸿蒙6期 语雀 vuex 在组件中使用 插件支持v2和v3 宏任务 和 微任务 多问问自己为什么 new的四步 查找数组里是否包含某个元素 同步任务、异步任务、微任务、宏任务

三大行业案例:AI大模型+Agent实践全景

本文将从AI Agent和大模型的发展背景切入&#xff0c;结合51Talk、哈啰出行以及B站三个各具特色的行业案例&#xff0c;带你一窥事件驱动架构、RAG技术、人机协作流程&#xff0c;以及一整套行之有效的实操方法。具体包含内容有&#xff1a;51Talk如何让智能客服“主动进攻”&a…

STM32G0B1 can Error_Handler 解决方法

问题现象 MCU上电&#xff0c;发送0x13帧数据固定进入 Error_Handler 硬件介绍 MCU :STM32G0B1 can:NSI1042 tx 接TX RX 接RX 折腾了一下午&#xff0c;无解&#xff0c;问题依旧&#xff1b; 对比测试 STM32G431 手头有块G431 官方评估版CAN 模块&#xff1b; 同样的…