6:参数化

承接前两篇:Pytest 用例规则 + 前后置 + 原生 assert 断言,本篇讲解参数化,接口自动化核心必备。日常接口需要覆盖正常、异常、边界多组入参,参数化实现「一套用例代码,多组数据循环执行」,大幅减少重复代码。

一、什么是参数化,为什么自动化必须用?

1. 概念

@pytest.mark.parametrize是 pytest 内置装饰器,批量传入多组测试数据,自动循环生成多条独立测试用例,一组数据对应 1 次用例执行。

2. 解决痛点

不使用参数化:多组入参就要复制多份测试函数,代码冗余、后期维护困难; 使用参数化:只写 1 次用例逻辑,数据源统一维护,新增 / 删减数据不用改动业务代码,接口边界、异常场景全覆盖。

接口测试场景:登录接口(正确账号、密码为空、错误密码、手机号格式错误)4 种场景,参数化 1 行配置 4 组数据即可。

二、基础语法格式

python 复制代码
@pytest.mark.parametrize(参数名字符串, 数据集列表)
def test_xxx(参数名):
    # 测试逻辑+断言
  • 第一个入参:"参数1,参数2" 多个参数用英文逗号分隔;
  • 第二个入参:嵌套列表 / 元组,每组元素一一对应前面的参数。

三、四种常用参数化写法(从单参数→类→全局→自定义数据源)

写法 1:函数级别参数化(单 / 多参数,项目最常用)

① 多参数传参(示例:计算器表达式校验,文档原示例优化)
python 复制代码
import pytest
# 参数1:计算公式字符串,参数2:预期结果
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
def test_eval(test_input, expected):
    # 执行计算公式
    res = eval(test_input)
    # 结合上篇断言知识点
    assert res == expected, f"公式{test_input}预期{expected},实际{res}"

执行pytest -vs,自动生成3 条独立用例 ,其中6*9=54≠42会单独失败,精准定位出错数据。

② 单参数简易示例
python 复制代码
@pytest.mark.parametrize("phone",["13800138000","","123456"])
def test_phone_format(phone):
    # 校验手机号长度
    assert len(phone)==11,f"手机号{phone}长度非法"

写法 2:测试类上参数化(类内所有 test 方法共用一套数据源)

装饰器写在 class 上方,类中全部以 test 开头的方法自动继承参数,每组数据所有方法循环执行一遍

python 复制代码
import pytest
# 两个参数 n:入参数字,expected:预期结果
@pytest.mark.parametrize("n,expected", [(1, 2), (3, 4)])
class TestClass:
    def test_simple_case(self, n, expected):
        assert n + 1 == expected
    def test_weird_simple_case(self, n, expected):
        assert (n * 1) + 1 == expected

执行结果:2 组数据 × 2 个用例 = 总共 4 条测试用例。

写法 3:模块全局参数化(当前 py 文件全部用例统一数据)

在脚本顶部定义全局变量pytestmark,本文件所有测试类、测试函数自动复用参数,不用逐个加装饰器

python 复制代码
import pytest
# 全局参数配置,本模块所有用例自动带入n、expected参数
pytestmark = pytest.mark.parametrize("n,expected", [(1, 2), (3, 4)])

class TestClass:
    def test_simple_case(self, n, expected):
        assert n + 1 == expected
    def test_weird_simple_case(self, n, expected):
        assert (n * 1) + 1 == expected

# 类外函数同样自动参数化
def test_global_demo(n,expected):
    assert n+1 == expected

写法 4:自定义函数返回数据源(数据和代码分离,实战优选)

把测试数据单独封装函数,后续拓展:从 json/yaml/excel 读取用例数据,实现数据代码完全分离

python 复制代码
import pytest
# 自定义数据源函数,后续可改成读取文件
def data_provider():
    return ["a", "b"]

# 直接传入函数名,自动读取返回列表
@pytest.mark.parametrize("data", data_provider())
def test_data(data):
    assert data is not None
    print(f"Testing with data provider: {data}")

拓展:企业项目中data_provider()内部写读取 yaml 接口用例,是主流接口自动化方案。

四、接口自动化实战案例(落地场景,结合 requests + 断言)

python 复制代码
import pytest
import requests

# 接口参数:帖子id,预期用户id
@pytest.mark.parametrize("post_id,expect_uid",[(1,1),(2,2),(99,99)])
def test_post_api(post_id,expect_uid):
    url = f"https://jsonplaceholder.typicode.com/posts/{post_id}"
    res = requests.get(url)
    # 断言状态码
    assert res.status_code == 200,f"接口{url}请求异常"
    json_data = res.json()
    # 校验返回用户id
    assert json_data["userId"] == expect_uid,f"帖子{post_id}预期用户{expect_uid},实际{json_data['userId']}"

执行后 3 个接口分别发起请求,任意一组数据出错单独标记失败,不影响其他用例执行。

五、进阶实用小技巧

1. 给每组用例自定义用例名称(ids 参数)

默认用例名是参数内容,可读性差,通过ids给每组数据起名,报告清晰

python 复制代码
@pytest.mark.parametrize("user,pwd",[("admin","123456"),("admin","")],ids=["正常登录","密码空登录"])
def test_login(user,pwd):
    pass

执行日志直接显示:test_login[正常登录]test_login[密码空登录]

2. 跳过指定参数用例(pytest.mark.skipif)

部分测试数据临时不需要执行,动态跳过单组用例

python 复制代码
data = [(1,2),(3,4)]
@pytest.mark.parametrize("n,e",data)
def test_skip(n,e):
    if n ==3:
        pytest.skip("该场景暂未开发完成,临时跳过")
    assert n+1 ==e

六、常见踩坑总结

  1. 参数数量匹配:参数名几个,每组元组必须对应相同元素,否则直接报参数不匹配报错;
  2. 全局 pytestmark 优先级:函数单独写了 parametrize 会覆盖全局配置;
  3. 数据分离规范:项目用例多了不要把数据硬编码写在装饰器里,统一放到函数 / 配置文件。
相关推荐
Web极客码1 小时前
突破并发瓶颈:云端高性能架构如何赋能海外 AI Agent 矩阵的高效产出
服务器·人工智能·架构
一个有温度的技术博主2 小时前
【VulnHub 实战】DC-1 靶机渗透测试笔记(一):信息收集与主机发现
服务器·网络·笔记
爱网络爱Linux3 小时前
Linux proc 目录安全加固
linux·运维·rhce·rhca·红帽认证·proc 目录安全加固
MindUp4 小时前
企业网盘权限模型解析:多层级访问控制与审计能力选型指南
java·linux·运维
持力行4 小时前
D-BUS会话总线
运维·网络
pt10434 小时前
思科网络自动化-API常用数据编码格式(JSON/XML/YAML)课程与实践
linux·服务器·网络
kdxiaojie4 小时前
Linux 驱动研究 —— I2C (5)
linux·运维·笔记·学习
独自归家的兔5 小时前
2026年7月2日 Docker 容器化部署 PaddleOCR-VL 实战(OpenAI 协议兼容 HTTP 调用)
运维·docker·容器
ZXXstarstar5 小时前
2026年电池安全使用年限的量化决策:什么时间到期最需要替换?
linux·运维·服务器·电池
网络小白不怕黑5 小时前
httpd监控
linux·运维·服务器