6:参数化

6:参数化 承接前两篇Pytest 用例规则 前后置 原生 assert 断言本篇讲解参数化接口自动化核心必备。日常接口需要覆盖正常、异常、边界多组入参参数化实现「一套用例代码多组数据循环执行」大幅减少重复代码。一、什么是参数化为什么自动化必须用1. 概念pytest.mark.parametrize是 pytest 内置装饰器批量传入多组测试数据自动循环生成多条独立测试用例一组数据对应 1 次用例执行。2. 解决痛点不使用参数化多组入参就要复制多份测试函数代码冗余、后期维护困难 使用参数化只写 1 次用例逻辑数据源统一维护新增 / 删减数据不用改动业务代码接口边界、异常场景全覆盖。接口测试场景登录接口正确账号、密码为空、错误密码、手机号格式错误4 种场景参数化 1 行配置 4 组数据即可。二、基础语法格式pytest.mark.parametrize(参数名字符串, 数据集列表) def test_xxx(参数名): # 测试逻辑断言第一个入参参数1,参数2多个参数用英文逗号分隔第二个入参嵌套列表 / 元组每组元素一一对应前面的参数。三、四种常用参数化写法从单参数→类→全局→自定义数据源写法 1函数级别参数化单 / 多参数项目最常用① 多参数传参示例计算器表达式校验文档原示例优化import pytest # 参数1计算公式字符串参数2预期结果 pytest.mark.parametrize(test_input,expected, [(35, 8), (24, 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*954≠42会单独失败精准定位出错数据。② 单参数简易示例pytest.mark.parametrize(phone,[13800138000,,123456]) def test_phone_format(phone): # 校验手机号长度 assert len(phone)11,f手机号{phone}长度非法写法 2测试类上参数化类内所有 test 方法共用一套数据源装饰器写在 class 上方类中全部以 test 开头的方法自动继承参数每组数据所有方法循环执行一遍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本文件所有测试类、测试函数自动复用参数不用逐个加装饰器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 n1 expected写法 4自定义函数返回数据源数据和代码分离实战优选把测试数据单独封装函数后续拓展从 json/yaml/excel 读取用例数据实现数据代码完全分离import pytest # 自定义数据源函数后续可改成读取文件 def data_provider(): return [a, b] # 直接传入函数名自动读取返回列表 pytest.mark.parametrize(data, data_provider()) def test_data(data): assert data is not None print(fTesting with data provider: {data})拓展企业项目中data_provider()内部写读取 yaml 接口用例是主流接口自动化方案。四、接口自动化实战案例落地场景结合 requests 断言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 fhttps://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给每组数据起名报告清晰pytest.mark.parametrize(user,pwd,[(admin,123456),(admin,)],ids[正常登录,密码空登录]) def test_login(user,pwd): pass执行日志直接显示test_login[正常登录]、test_login[密码空登录]。2. 跳过指定参数用例pytest.mark.skipif部分测试数据临时不需要执行动态跳过单组用例data [(1,2),(3,4)] pytest.mark.parametrize(n,e,data) def test_skip(n,e): if n 3: pytest.skip(该场景暂未开发完成临时跳过) assert n1 e六、常见踩坑总结参数数量匹配参数名几个每组元组必须对应相同元素否则直接报参数不匹配报错全局 pytestmark 优先级函数单独写了 parametrize 会覆盖全局配置数据分离规范项目用例多了不要把数据硬编码写在装饰器里统一放到函数 / 配置文件。