当前位置:首页 > 文章列表 > 文章 > python教程 > pytest 参数化 fixture怎样让不同输入复用同一组资源怎样完成一个可复用的最小示例

pytest 参数化 fixture怎样让不同输入复用同一组资源怎样完成一个可复用的最小示例

来源:17golang原创 2026-11-10 05:35:32 0浏览 收藏

不同输入复用同一组资源,通常让测试函数负责输入参数化,让 fixture 的 scope 决定资源生命周期;如果变化的是资源配置,再使用 fixture params 或 indirect。参数化本身并不保证所有用例共享一个实例,资源复用也不应顺带共享上一例写入的数据。

假设要检查三种数值的入库逻辑,昂贵的是连接准备,变化的只是写入值。下面把模块共享连接与逐例事务隔离拆开,避免为减少初始化次数而引入测试顺序依赖。官方文档地址:https://docs.pytest.org/en/stable/how-to/fixtures.html。

1. 输入变化与资源变化要分开

先问变化发生在哪一层:若只是 value 不同,用 mark.parametrize;若同一套逻辑要面对不同后端配置,让参数进入资源 fixture。默认 fixture 是 function 作用域,每个用例独立构造;module 可以在同一模块内复用,session 则具有更大的共享范围。

变化对象建议位置
业务输入测试函数 parametrize
资源构造配置fixture params 或 indirect
需要复用的连接适当扩大连接 fixture scope
每例写入状态function fixture 初始化或回滚

扩大 scope 只定义生命周期,不自动让资源线程安全、事务安全,也不意味着参数化资源永远只创建一次。pytest 缓存当前 fixture 实例,参数切换可能导致同一 scope 内多次构造。

2. 给共享连接加上逐例回滚

保存为 test_shared_db.py。测试模块持有 db 连接;case_db 依赖连接,为测试函数提供逐例事务和事务回滚;参数输入仅由测试函数消费。这些依赖决定初始化边界,不能靠函数定义顺序代替。

模块资源与用例隔离边界
模块资源与用例隔离边界;静态关系说明图,非截图或运行证据。
import sqlite3
import pytest

@pytest.fixture(scope="module")
def db():
    # 同一模块复用一条内存连接,连接结束时关闭
    connection = sqlite3.connect(":memory:")
    try:
        connection.execute("CREATE TABLE sample (value INTEGER NOT NULL)")
        connection.commit()
        yield connection
    finally:
        connection.close()

@pytest.fixture
def case_db(db):
    # 每例独立事务;测试内禁止 commit,以保持回滚隔离
    db.execute("BEGIN")
    try:
        yield db
    finally:
        db.rollback()

@pytest.mark.parametrize("value", [2, 7, 11], ids=["small", "mid", "large"])
def test_insert(case_db, value):
    # 复用连接但不复用前一例写入的行,绑定参数避免拼接 SQL
    case_db.execute("INSERT INTO sample(value) VALUES (?)", (value,))
    count, total = case_db.execute(
        "SELECT COUNT(*), SUM(value) FROM sample"
    ).fetchone()
    assert count == 1
    assert total == value
# 在项目虚拟环境中安装 pytest,再执行这一份示例
python -m pip install pytest
python -m pytest -q --setup-show test_shared_db.py

本例未在本文环境运行。按代码语义,应收集三项输入,每项插入后只能看到一行;模块连接只供该模块中的相关测试复用,case_db 在每项结束后回滚。--setup-show 用于读者观察 setup/teardown 归属,不提供虚构的执行耗时。

这是一份受限的 SQLite 示例:测试和被测代码不能主动 commit,否则外部回滚无法撤销已提交的数据;不能把多线程或并发用例直接塞进同一连接。真实数据库应根据事务、连接池与迁移策略设计隔离,必要时改用独立库、schema 或数据命名空间。

yield 前创建资源失败时,yield 后清理段不会按正常路径执行;因此使用 try/finally 包围已经获得的连接。测试断言失败时,逐例 fixture 的 finally 仍负责回滚,模块 fixture 最后负责关闭连接。

3. 让资源配置参数进入 fixture

当 strict、relaxed 是不同构造配置时,可以通过 indirect 声明 backend 参数交给同名 fixture,再由 request.param 读取。这里用内存字典模拟资源对象,不代表真实连接或网络会话;backend fixture 用默认作用域确保每例独立容器。

配置参数与请求对象的依赖
配置参数与请求对象的依赖;静态关系说明图,非截图或运行证据。
import pytest

@pytest.fixture
def backend(request):
    # 参数是配置而非预先创建的资源,构造发生在 fixture 执行时
    return {"mode": request.param, "items": []}

@pytest.mark.parametrize(
    "backend", ["strict", "relaxed"], indirect=["backend"]
)
def test_backend(backend):
    # 默认 function 作用域让每例获得独立可变容器
    backend["items"].append("demo")
    assert backend["mode"] in {"strict", "relaxed"}
    assert backend["items"] == ["demo"]

可将第二段独立保存为 test_backend.py 再运行。它定义两项配置,重点是资源构造发生在 fixture 执行阶段,而非在参数列表里预先创建可变资源。不带 indirect 时,参数值会直接作为测试参数传入,并不会自动调用同名 fixture 完成配置。

如果多个测试都要遍历同一组配置,可以把配置移到 @pytest.fixture(params=[...]),让依赖它的测试自动扩展。不要同时对同一参数使用两套不一致的参数来源;多个独立参数维度还会形成组合,测试数量可能乘积增长。

遇到 ScopeMismatch 时,应检查宽作用域 fixture 是否依赖了更窄作用域资源。例如 module fixture 不能直接依赖 function fixture。对于并行测试,session 资源通常也不是跨所有工作进程只创建一次,部署外部共享资源要有明确的进程间协调。

测试数据为什么会串到下一例?

共享可变资源没有重置。扩大 scope 后,需增加逐例清理、回滚或独立数据边界,不能只靠参数化。

为什么测试拿到的是字符串配置?

检查是否声明 indirect,以及参数名与 fixture 名是否一致。直接参数化与间接参数化的输入位置不同。

scope 越大越好吗?

初始化成本与隔离难度要一起考虑。资源便宜、状态复杂时,function 通常更容易保持独立性。

间接参数化官方示例:https://docs.pytest.org/en/stable/example/parametrize.html。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
NumPy dtype 与 copy数组转换后为什么修改会影响原数据怎样在批处理代码中减少额外分配NumPy dtype 与 copy数组转换后为什么修改会影响原数据怎样在批处理代码中减少额外分配
上一篇
NumPy dtype 与 copy数组转换后为什么修改会影响原数据怎样在批处理代码中减少额外分配
systemd-journald 限流日志突发时为什么出现 rate limit 提示怎样完成一个可复用的最小示例
下一篇
systemd-journald 限流日志突发时为什么出现 rate limit 提示怎样完成一个可复用的最小示例
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    965次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    966次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1077次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1057次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    888次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码