pytest参数化
pytest参数化
1. Fixture参数之params参数可实现参数化
(参数可以为list和tuple,或者字典列表,字典元祖等)
1.1 参数化传单个参数

1 # -*-coding: utf-8 -*- 2 import pytest 3 import requests 4 5 def userinfo(): 6 users = ['13630000009','18290000007','13040000004'] 7 return users 8 9 @pytest.fixture(params=userinfo()) 10 def login(request): 11 yield request.param 12 #删除节点的操作,新增合作方、新增商场、新增出入口 13 14 @pytest.fixture(params=userinfo()) 15 def login1(request): 16 yield request.param 17 #删除节点的操作,新增合作方、新增商场、新增出入口 18 19 def test_login(login,login1,): 20 url= "https://172.16.100.154/auth/getAccessTokenV2" 21 data = { 22 "username": login, 23 "passwd": 'a34fca232356ab316d3bb293b3f3d82d', 24 "randStr": None, 25 "ticket": None, 26 } 27 r = requests.post(url=url,json=data,verify=False) 28 print('登录结果',r.text) 29 print('调用的测试数据:' + login)
此例中test_login方法被执行了三次,分别使用的数据为'13630000009','18290000007','13040000004',此结果类似于ddt数据驱动的功能。特别注意:这里的request参数名是固定的,然后request.param的param没有s
可以把return request.param改成yield request.param,yield也是返回的意思,它和return的区别在于return返回后后面不能接代码,但是yield返回后,后面还可以接代码。
yield:方法调用夹具时,有删除依赖时,记住先进后出原则,即放在最后面最先删除
1.2 参数化传多个参数

1 import pytest 2 import requests 3 4 # 测试账号数据 5 test_user_data = [{"user": "17530000005", "passwd": "b1b3e46675227369bd396eb44df1c900"}, 6 {"user": "15310000000", "passwd": "b1b3e46675227369bd396eb44df1c900"}] 7 8 @pytest.fixture(params=test_user_data) 9 def login(request): 10 user = request.param["user"] 11 passwd = request.param["passwd"] 12 print("\n") 13 print("登录账户:%s" % user) 14 print("登录密码:%s" % passwd) 15 yield user,passwd 16 17 18 def test_login(login): 19 """登录用例""" 20 url= "https://172.16.100.154/auth/getAccessTokenV2" 21 data = { 22 "username": login[0], 23 "passwd": login[1], 24 "randStr": None, 25 "ticket": None, 26 } 27 r = requests.post(url=url,json=data,verify=False) 28 print('登录结果',r.text) 29 print("\n")
1.3 Fixture其他参数:
1.3.1.autouse参数:在夹具中设置autouse=True为自动调用执行,

1 import pytest 2 3 # @pytest.fixture(autouse=True) #设置为True让autouse生效 4 # def setUp(): 5 # print('\nsetUp') 6 # yield 7 # print('\ntearDown') 8 # 9 # def testcase01(): 10 # print('1111111111') 11 # 12 # def testcase02(): 13 # print('2222222222') 14 15 # if __name__=='__main__': 16 # pytest.main(['-s', '-v', "test13.py"])\ 17 # 18 @pytest.fixture() #不设置autouse是默认autouse为false 19 def setUp(): 20 print('\nsetUp') 21 yield 22 print('\ntearDown') 23 24 def testcase01(setUp): 25 print('1111111111') 26 27 def testcase02(): 28 print('2222222222') 29 30 if __name__=='__main__': 31 pytest.main(['-s', '-v', "test13.py"])
1.3.2.ids参数:ids参数用于描述每个用例的运行场景

1 import pytest 2 import requests 3 4 5 # 测试账号数据 6 test_user_data = [{"user": "17530000005", "passwd": "b1b3e46675227369bd396eb44df1c900"}, 7 {"user": "15300000000", "passwd": "b1b3e46675227369bd396eb44df1c900"}] 8 9 @pytest.fixture(params=test_user_data,ids=[ 10 "输入账号1,密码1,登录成功", 11 "输入账号2,密码2,登录成功", 12 ]) 13 def login(request): 14 user = request.param["user"] 15 passwd = request.param["passwd"] 16 yield user,passwd 17 18 19 def test_login(login): 20 """登录用例""" 21 url= "https://172.16.100.154/auth/getAccessTokenV2" 22 data = { 23 "username": login[0], 24 "passwd": login[1], 25 "randStr": None, 26 "ticket": None, 27 } 28 r = requests.post(url=url,json=data,verify=False)
运行结果
1.3.3. name参数:相对于把被fixture标记的方法重命名,主要是命名为中文,让使用起来更易读。如下图所示案例:
注意点:设置了name即夹具的别名,就不能再使用函数名调用了,使用函数名调用会报错
2. 使用@pytest.mark.parametrize()方法实现参数化
方法详情:
parametrize(argnames,argvalues,indirect=False,ids=None,scope=None)
常用参数:
argnames:参数名
argnames:参数值(可以为list和tuple,或者字典列表,字典元组等),参数值有N个,用例就会执行N次。
3.1. 使用方式一

1 # -*-coding: utf-8 -*- 2 3 import pytest 4 import requests 5 6 # 测试账号数据 7 test_user_data = [{"user": "17530000005", "passwd": "b1b3e46675227369bd396eb44df1c900"}, 8 {"user": "15300000000", "passwd": "b1b3e46675227369bd396eb44df1c900"}] 9 10 @pytest.mark.parametrize("case_info",test_user_data) 11 def test_login(case_info): 12 print("\n") 13 print("用户名",case_info['user']) 14 print("密码",case_info['passwd']) 15 url= "https://172.16.100.154/auth/getAccessTokenV2" 16 data = { 17 "username": case_info['user'], 18 "passwd": case_info['passwd'], 19 "randStr": None, 20 "ticket": None, 21 } 22 r = requests.post(url=url,json=data,verify=False) 23 print('登录结果',r.text)
3.2 使用方式二:类似于@unpack解包功能实现参数

1 # -*-coding: utf-8 -*- 2 import pytest 3 import requests 4 5 # 测试账号数据 6 test_user_data = [('17530000005', 'b1b3e46675227369bd396eb44df1c900'), 7 ('15300000000', 'b1b3e46675227369bd396eb44df1c900')] 8 9 @pytest.mark.parametrize('user,passwd',test_user_data) 10 def test_login(user,passwd): 11 print("\n") 12 print("用户名",user) 13 print("密码",passwd) 14 url= "https://172.16.100.154/auth/getAccessTokenV2" 15 data = { 16 "username": user, 17 "passwd": passwd, 18 "randStr": None, 19 "ticket": None, 20 } 21 r = requests.post(url=url,json=data,verify=False) 22 print('登录结果',r.text)
4. 数据驱动 Vs 关键字驱动
4.1 数据驱动自动化测试
在自动化测试框架中,从csv或excel或ymal读取数据、输出数据都在文件中执行,一个业务的实际返回值与业务的预期返回值都在数据文件中操作而不是在脚本里去执行校验,这时候数据文件和脚本驱动为数据驱动框架。
优点和缺点
1)优点:
1.解耦合、测试数据预期结果与脚本分开
2.对于业务的改版或字段的增删只需去修改脚本或者数据源
3.避免重复编写脚本数据
2)缺点:
1.随着业务量的增加、改版迭代次数快不方便维护
2.长时间可能会丢失数据
3.数据文件多、难以修改业务数据
4.2 关键字驱动
基于数据驱动之上建立的关键字驱动,从一个关键字的整合面对不同测试方法调用。从多个测试方法函数整合完成进阶的关键字驱动,从数据和关键字的组合达到一个关键字驱动的效果。
关键字自动化测试驱动
在关键字驱动框架中,你可以创建一些函数或者一些测试方法。从函数库中读取关键字然后做相关调用。这种自动化驱动模型主要核心由数据驱动引擎、组件函数、支持库和应用映射表组成。自动化测试首先由初始化脚本执行,这个脚本把高层测试表传递给高层驱动,高层驱动在处理这些表过程中,遇到中层驱动,中层处理也做中层处理。在底层处理时,尝试底层测试同步 ,关键字驱动是对数据驱动做改善。
4.3 有哪几种数据驱动方式
1.以硬编码的方式写在代码里,简单直观,但代码和数据未分离,不方便以后维护。
2.从文件读取数据,如csv,excel、txt、xml等格式文件。不用修改测试逻辑,只需要维护测试数据。
excel表读数据代码示例

1 import pytest, xlrd, os, requests, json 2 3 # 获取excel用例数据 4 def get_case_data(): 5 case_path = r"E:\scripts\newplatform\linshi\interface\yanshi\test_data.xlsx" 6 book = xlrd.open_workbook(case_path) 7 sheet = book.sheet_by_name('Sheet1') 8 case = [] 9 for i in range(0, sheet.nrows): 10 if sheet.row_values(i)[0] == 'mall用户登录': 11 case.append(sheet.row_values(i)) 12 return case 13 14 #注意点:excel中的json数据应为双引号,否在json.loads时会报错JsonEncodeError 15 16 class Test(): 17 18 # 调用获取测试用例数据 19 case_data = get_case_data() 20 21 # 使用装饰器参数化用例数据 22 @pytest.mark.parametrize('Function,TestCase,URL,Parameters', case_data) #注意此处填写的参数应与表格一致,及表格多少列就将其参数名都写出来,否则会报错 23 def test_login1(self, Function, TestCase,URL, Parameters): 24 25 print(json.loads(Parameters)) 26 r = requests.post(url=URL,json=json.loads(Parameters),verify=False) 27 print(r.text) 28 assert r.text==r.text 29 30 if __name__ == "__main__": 31 pytest.main(["-s","-v","-w", "exceltest.py"])
3.直接调用接口获取数据源。
4.本地封装一些生成数据的方法。
Redis
4.4 数据驱动的优点
1. 像在循环里一样,自动遍历所有数据组合。
2. 某一组数据执行测试方法失败,不会影响其他数据组合继续执行。
3. 测试代码不用加过多的数据判断,要的只是对被测代码的数据输出和结果断言。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!