pytest 参数化是什么
@pytest.mark.parametrize 把一组组数据展开成相互独立的用例:每组数据单独计数、单独失败定位,报错只影响本组数据。它是数据驱动测试在 pytest 里的标准做法,边界值矩阵、多环境组合、状态码校验这类「同一逻辑、多组输入」的场景用它最直接。多层叠加时按笛卡尔积展开,需要用例数量提前心里有数。
基本信息
| 装饰器 | @pytest.mark.parametrize('参数名', 数据列表) |
|---|---|
| 命名 | ids 参数为每组数据取可读名,报告中直接显示 |
| 单例定制 | pytest.param 给个别数据单独配 id 或 marks(如 xfail) |
| 多层叠加 | 多个 parametrize 叠加时按笛卡尔积组合展开 |
| 数据来源 | 字面量列表、文件读取、fixture 间接参数化(indirect) |
| 空参数集 | 参数列表为空时该用例被跳过并给出警告 |
参数化示例
参数化示例
import pytest
# 单层参数化:每组数据独立成用例,失败互不干扰
@pytest.mark.parametrize('value,expected', [(1, 2), (2, 4), (9, 18)],
ids=['one', 'two', 'nine'])
def test_double(value, expected):
assert double(value) == expected
# 多层叠加:按笛卡尔积展开,2 层各 2 组就是 4 个用例
@pytest.mark.parametrize('x', [0, 1])
@pytest.mark.parametrize('y', [10, 20])
def test_cross(x, y): ...
# 单例定制:只给个别数据挂 id 与标记
@pytest.mark.parametrize('v', [pytest.param(1, id='ok'),
pytest.param(0, id='zero', marks=pytest.mark.xfail)])
def test_edge(v): ...典型使用场景
- 边界矩阵:把等价类与边界值整理成一张数据表,逐组展开断言。
- 接口矩阵:同一接口按状态码、角色、参数组合逐组校验。
- 多环境验证:同一用例在开发、预发等不同配置下批量执行。
- 数据文件驱动:从 CSV、JSON、YAML 读用例数据,测试代码与数据分离。
- 失败精确定位:每组数据独立命名,报告里一眼看出是哪组输入挂了。
- 标记分组:给个别数据挂 xfail 或自定义标记,精确控制执行范围。
失败粒度是选它的核心理由:循环里跑多组数据只报最后一个断言,参数化则逐组独立报告、独立重跑。
ids 不写会自动生成下标名:数据一多报告就像天书,给关键数据补上可读 id 的成本极低、收益极高。
组合层数增加前先估算用例总量:三个维度各 5 组就是 125 个用例,规模失控时改用成对组合(pairwise)控制。
参数数据同样纳入版本管理:数据与用例同库同评审,避免脚本更新后数据口径脱节。