【pytest】使用 marker 向 fixture 传递数据 - 指南
文章目录
- 核心概念解析
- 1. 传统的单向数据流
- 2. 使用 markers 的双向数据流
- 代码逐行解析
- 关键技术组件详解
- 1. `request` fixture
- 2. `get_closest_marker()` 方法
- 3. Marker 对象的结构
- 实际应用场景
- 场景1:动态数据库配置
- 场景2:不同环境的测试数据
- 场景3:参数化 fixture 行为
- 高级用法
- 1. 多个 markers 的组合使用
- 2. 与参数化结合使用
- 错误处理和最佳实践
- 1. 健壮的 marker 处理
- 2. 提供默认值和回退
- 与类似技术的对比
- 1. 与 `pytest.param` 的对比
- 2. 与 fixture 参数的对比
- 总结
pytest 允许测试函数通过 markers 向 fixture 传递数据,实现了测试与 fixture 之间的双向通信。
核心概念解析
1. 传统的单向数据流
在普通的 pytest 用法中,数据流是单向的:
fixture → 测试函数
fixture 准备数据,测试函数消费数据。
2. 使用 markers 的双向数据流
通过这种技术,实现了双向通信:
测试函数 → (通过markers) → fixture → 测试函数
代码逐行解析
import pytest
@pytest.fixture
def fixt(request): # request 是内置 fixture,提供测试上下文信息
# 获取测试函数上最近的 "fixt_data" marker
marker = request.node.get_closest_marker("fixt_data")
if marker is None:
# 处理没有 marker 的情况
data = None
else:
# 获取 marker 的第一个参数
data = marker.args[0]
# 对数据进行处理并返回
return data
@pytest.mark.fixt_data(42) # 通过 marker 向 fixture 传递数据
def test_fixt(fixt):
assert fixt == 42 # fixture 返回了通过 marker 传递的数据
关键技术组件详解
1. request fixture
request 是 pytest 的内置 fixture,它提供了访问测试上下文的能力,包含:
request.node:当前测试项目(函数、类等)request.config:pytest 配置对象request.function:测试函数对象request.cls:测试类(如果有)
2. get_closest_marker() 方法
这个方法用于获取最近的指定 marker:
marker = request.node.get_closest_marker("fixt_data")
- 返回
pytest.Mark对象或None - 可以访问 marker 的参数和关键字参数
3. Marker 对象的结构
@pytest.mark.fixt_data(42, "hello", key="value")
def test_example():
pass
# 在 fixture 中可以这样访问:
marker = request.node.get_closest_marker("fixt_data")
print(marker.args) # (42, "hello")
print(marker.kwargs) # {"key": "value"}
实际应用场景
场景1:动态数据库配置
import pytest
@pytest.fixture
def database(request):
# 获取测试的数据库配置
marker = request.node.get_closest_marker("db_config")
if marker:
db_name = marker.args[0]
timeout = marker.kwargs.get("timeout", 30)
else:
db_name = "test_db"
timeout = 30
# 根据配置创建数据库连接
db = connect_to_database(db_name, timeout=timeout)
yield db
db.close()
@pytest.mark.db_config("users_db", timeout=60)
def test_user_operations(database):
# 使用专门配置的 users_db 进行测试
result = database.query("SELECT * FROM users")
assert len(result) > 0
场景2:不同环境的测试数据
@pytest.fixture
def test_data(request):
marker = request.node.get_closest_marker("test_env")
env = "development"
if marker:
env = marker.args[0]
# 根据环境加载不同的测试数据
if env == "production":
return load_production_data()
elif env == "staging":
return load_staging_data()
else:
return load_development_data()
@pytest.mark.test_env("production")
def test_production_scenario(test_data):
# 使用生产环境数据进行测试
assert test_data.is_production_ready()
场景3:参数化 fixture 行为
@pytest.fixture
def api_client(request):
marker = request.node.get_closest_marker("api_version")
version = "v1"
if marker:
version = marker.args[0]
# 创建对应版本的 API 客户端
client = APIClient(version=version)
yield client
client.cleanup()
@pytest.mark.api_version("v2")
def test_new_api_features(api_client):
# 测试 v2 版本的新功能
response = api_client.post("/new-endpoint")
assert response.status_code == 200
高级用法
1. 多个 markers 的组合使用
@pytest.fixture
def complex_fixture(request):
# 获取多个不同的 markers
db_marker = request.node.get_closest_marker("database")
cache_marker = request.node.get_closest_marker("cache")
auth_marker = request.node.get_closest_marker("auth")
# 组合配置复杂的测试环境
config = {
"database": db_marker.args[0] if db_marker else "default_db",
"cache_enabled": bool(cache_marker),
"auth_required": auth_marker.kwargs if auth_marker else {}
}
return setup_environment(config)
@pytest.mark.database("replica_db")
@pytest.mark.cache
@pytest.mark.auth(role="admin", permissions=["read", "write"])
def test_complex_scenario(complex_fixture):
# 使用复杂配置的环境进行测试
pass
2. 与参数化结合使用
@pytest.fixture
def configured_resource(request):
marker = request.node.get_closest_marker("resource_config")
if marker:
config = marker.args[0]
else:
config = {"size": "medium", "type": "default"}
return create_resource(config)
@pytest.mark.parametrize("input,expected", [(1, 2), (3, 4)])
@pytest.mark.resource_config({"size": "large", "type": "performance"})
def test_with_params(configured_resource, input, expected):
# 所有参数化测试用例都使用相同的资源配置
result = configured_resource.process(input)
assert result == expected
错误处理和最佳实践
1. 健壮的 marker 处理
@pytest.fixture
def robust_fixture(request):
marker = request.node.get_closest_marker("config")
try:
if marker is None:
raise pytest.UsageError("config marker is required")
if len(marker.args) == 0:
raise pytest.UsageError("config marker requires at least one argument")
config = marker.args[0]
# 验证配置格式
if not isinstance(config, dict):
raise pytest.UsageError("config must be a dictionary")
except pytest.UsageError as e:
pytest.fail(f"Fixture configuration error: {e}")
return create_configured_resource(config)
@pytest.mark.config({"option": "value"})
def test_with_proper_config(robust_fixture):
assert robust_fixture.is_configured()
2. 提供默认值和回退
@pytest.fixture
def flexible_fixture(request):
marker = request.node.get_closest_marker("settings")
# 提供合理的默认值
defaults = {
"timeout": 30,
"retries": 3,
"mode": "standard"
}
if marker:
# 合并默认值和 marker 提供的设置
user_settings = marker.kwargs
settings = {**defaults, **user_settings}
else:
settings = defaults
return create_service(settings)
与类似技术的对比
1. 与 pytest.param 的对比
# 使用 pytest.param(间接参数化)
@pytest.mark.parametrize("fixt_input", [
pytest.param("special_case", marks=pytest.mark.special),
"normal_case"
])
def test_param_style(fixt_input):
# fixt_input 直接作为参数传递
pass
# 使用 marker 直接传递
@pytest.mark.special_config("special_value")
def test_marker_style(special_fixture):
# 通过 fixture 获取配置
pass
2. 与 fixture 参数的对比
# 使用 fixture 参数(需要间接 fixture)
@pytest.fixture
def parametrized_fixture(request):
return request.param
@pytest.mark.parametrize("parametrized_fixture", [1, 2, 3], indirect=True)
def test_indirect(parametrized_fixture):
assert parametrized_fixture in [1, 2, 3]
# 使用 marker(更直接)
@pytest.mark.data(42)
def test_marker(data_fixture):
assert data_fixture == 42
总结
这种使用 markers 向 fixtures 传递数据的技术提供了:
- 灵活性:测试可以动态配置 fixture 的行为
- 可读性:测试意图通过 markers 清晰表达
- 复用性:同一个 fixture 可以适应多种测试场景
- 类型安全:可以在 fixture 中验证和处理传入的数据
虽然这是一个高级特性,但在需要复杂测试配置或环境设置的场景中,它能够显著提高测试代码的质量和可维护性。关键是要确保良好的文档和错误处理,因为这种隐式的数据传递可能会增加代码的复杂性。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/955549.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!相关文章
2025年11月性价比高的学习机品牌推荐:热门排行深度对比
临近年底,家长群里最热的话题之一,就是“该给孩子换一台怎样的学习机”。双减之后,校内作业量下降,家庭自主学习时间反而拉长;加上各地中高考命题越来越强调素养与情境,单纯刷题已难提分。于是,一台能把“学、练…
Ubuntu 20 中 root 默认密码
Ubuntu 20 中 root 默认密码Ubuntu 20 中 root 用户默认没有设置密码,其账户也是被禁用的。
Ubuntu 系统为了提高安全性,设计上通过 sudo 权限来管理系统,而不是直接启用 root 账户。如果需要使用 root 账户,可以通…
2025年11月性价比高的学习机品牌推荐榜:五强排名与价值对比
“孩子成绩波动大,线下辅导太贵,网课又管不住,一台机器能不能把教材同步、错题订正、名师讲解、护眼、家长管控一次解决?最好价格别超过一台中端手机。”这是后台留言里出现频率最高的焦虑。教育部“双减”之后,家…
2025年和君有约传媒科技:AI获客技术全景解析与增长逻辑揭秘
引言
本文从“技术—场景—数据”三维交叉视角出发,对和君有约传媒科技(郑州)有限公司的AI获客体系进行拆解,为正在评估智能营销供应商的企业提供一份可落地的客观参考。
背景与概况
和君有约传媒科技(郑州)有限…
2025年和君传媒:AI获客技术深度解析与增长引擎盘点
引言
本文聚焦“技术落地与行业适配”维度,拆解和君传媒如何在AI搜索与短视频双场景中,将算法红利转化为可验证的企业订单,为正在评估智能化获客方案的读者提供一份可落地的客观参考。
背景与概况
和君有约传媒科技…
2025年和君传媒深度揭秘:AI获客技术如何重塑企业增长引擎
引言
本文聚焦“技术落地可行性”这一核心维度,拆解和君传媒GEO与短视频AI获客系统在多行业中的真实适配表现,为企业评估是否引入提供可量化的客观参照。
背景与概况
和君有约传媒科技(郑州)有限公司面向金融、教育…
2025年11月性价比高的学习机品牌推荐榜:读书郎领衔五强对比评测
“孩子马上小升初,线下辅导班动辄上万,想选一台能用六年的学习机,又怕买贵、买错、买成游戏机。”这是家长群里出现频率最高的留言。教育部《2024全国中小学生在线学习调研》显示,近七成家庭把“一次投入、长期可用…
2025年11月全屋定制环保材料公司推荐榜:五强对比评测助你安心选
正在筹备新房装修或旧屋改造的你,如果希望“一站式”搞定柜体、墙板、木门、卫浴收纳,却又担心甲醛、TVOC超标,那么“全屋定制环保材料公司”这十个字大概率已经出现在你的搜索记录里。2025年第三季度,住建部《住宅…
2025年11月全屋定制环保材料公司排名:五强综合实力对比
正在装修或准备翻新的你,如果既想拥有“拎包入住”的省心,又担心甲醛、TVOC等隐形污染,全屋定制环保材料公司就成了绕不开的关键词。2025年第三季度住建部《住宅室内装修污染控制调研》显示,78%的业主把“环保等级…
没有 AI,没有融资,一个 17K Star 开源项目的真实收入
前情
我们在去年 NocoBase 发布 1.0 的时候,写过一篇文章:《一个不知名的开源产品可以带来多少收入》,分享了过去 12 个月 NocoBase 的收入。如今又一年过去了,在这一年里世界发生了很大的变化,家喻户晓的 ChatGP…
一体化 ITSM 平台选型新思路:怎样打通 IT 服务与业务需求的割裂堵点?
一体化 ITSM 平台选型新思路:怎样打通 IT 服务与业务需求的割裂堵点?$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");本文对比主流ITSM产品核心能力与适配…
2025 年 11 月四爪锅炉炉排,三爪锅炉炉排,锅炉炉排省煤器厂家最新推荐,实力品牌深度解析采购无忧之选!
引言
近期,行业协会针对四爪锅炉炉排、三爪锅炉炉排、锅炉炉排省煤器产品开展专项测评,本次测评覆盖近 50 家主流生产厂家,采用 “技术参数检测 + 实际工况模拟 + 市场口碑调研” 三维评估体系。技术参数检测环节,…
P10.Transforms的使用(二)
P10.Transforms的使用(二)10.1为什么需要Tensor数据类型
1.通过transforms.ToTensor去看两个问题:
①transforms的使用(pytorch);②为什么需要ToTensor数据类型。
2.为什么需要ToTensor数据类型?
因为他包装了我…
Discuz建站经验:Discuz论坛管理员怎么重置修改用户密码?
如果你的网站使用的是Discuz论坛模板,用户忘记了密码并且验证邮箱出了问题,那还有没有其它办法重置用户的密码呢?答案是有的,管理员可在管理中心重置用户的密码。下面我们就来看看管理员该如何重置Discuz论坛用户的…
2025年压缩机闭式冷却塔优质厂家权威推荐榜单:闭式凉水塔/闭式冷却塔/热处理闭式冷却塔源头厂家精选
在工业制冷领域,压缩机闭式冷却塔作为关键设备,其性能直接影响生产效率和能源消耗。据2025年行业数据显示,我国闭式冷却塔市场规模已达186亿元,年增长率稳定在12%以上。
随着节能减排政策的深入推进,高效节能型闭…
2025年气凝胶绝热材料源头厂家权威榜单:气凝胶隔热涂料/屋顶隔热涂料/纳米涂层镀膜源头厂家精选
气凝胶绝热材料作为新一代高效保温材料,以其优异的隔热性能、显著减重的效果和长寿命特性,正在成为工业节能、建筑保温和新能源领域的重要选择。本文将基于技术实力、产品性能、市场应用等多维度指标,为您推荐2025年…
【LVGL】外部 SDRAM 的使用方法
引言
LVGL 有时候所需的空间或者缓存会很大,这时候就可以用上外部的 SDRAM 来拓展空间。
使用 SDRAM 的两种情况使用外部 SDRAM 超方便的方法
参考以下博客:
【STM32H743IIT6 系列】将外部SDRAM作为内部RAM使用的超简…
数据库基准测试4:HammerDB测试脚本运用(for Oracle)
0.前面要说的话
之前章节简单介绍了一下hammerdbcli的使用方法,但通过命令行的方式不适合大批量数据基准测试(灌了3000仓库的tpcc数据在虚拟 机上耗时超过了1天多),实际hammerdb已经内置了多种数据库类型的基准测试…