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)
View Code
复制代码

此例中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")
View Code
复制代码

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"])
View Code
复制代码

 

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)
View Code
复制代码

运行结果

 

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)
View Code
复制代码

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)
View Code
复制代码

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"])
View Code
复制代码

3.直接调用接口获取数据源。
4.本地封装一些生成数据的方法。
Redis

 

4.4 数据驱动的优点


1. 像在循环里一样,自动遍历所有数据组合。
2. 某一组数据执行测试方法失败,不会影响其他数据组合继续执行。
3. 测试代码不用加过多的数据判断,要的只是对被测代码的数据输出和结果断言。


posted @   小菜鸟qing  阅读(1199)  评论(0编辑  收藏  举报
编辑推荐:
· 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框架的用法!
点击右上角即可分享
微信分享提示