pytest数据驱动及conftest文件及装饰器使用
一:数据驱动
file_operate.py文件
# coding=utf-8
"""@Project :pachong-master @File :file_operate.py@Author :gaojs@Date :2022/7/1 23:00@Blogs : https://www.gaojs.com.cn
"""
import openpyxl as xl
import yamldef read_excel(filepath, sheet_name):"""读取数据,将其转换成所需格式:return:"""# 得到整个excel文档对象wb = xl.load_workbook(filepath)# 获取某个sheet工作表数据sheet_data = wb[sheet_name]# 定义空列表,用来存储多行数据,每行数据都是一个列表data = []# 得到总行数lines_count = sheet_data.max_row# 得到总列数cols_count = sheet_data.max_columnfor li in range(2, lines_count+1):line = []for co in range(1, cols_count+1):cell = sheet_data.cell(li, co).valueif cell is None:cell = ''line.append(cell)data.append(line)return datadef write_excel(filepath, sheet_name, row, col, text):"""写入内容:return:"""wb = xl.load_workbook(filepath)sheet_data = wb[sheet_name]# 写入数据sheet_data.cell(row=row, column=col, value=text)wb.save(filepath)def read_yaml(filepath):"""读取yaml文件:return:"""with open(filepath, mode='r', encoding='utf-8') as fin:content = yaml.load(fin, Loader=yaml.FullLoader)return contentdef write_yaml(filepath, text):"""写入文件内容:return:"""with open(filepath, mode='w', encoding='utf-8') as fin:yaml.dump(text, fin, Dumper=yaml.Dumper)if __name__ == '__main__':# print(read_excel('./test_data.xlsx', '数据驱动数据'))# write_excel('./test_data.xlsx', '数据驱动数据', row=6, col=6, text='gaojianshuai')print(read_yaml('./test_data.yml').get('数据驱动数据'))write_yaml('./test_data1.yml', {'userName': 'gaojs', 'password': '1234'})
test_data.yml文件
# 数据驱动接口数据数据驱动数据:- ['admin', 1234, 200, 0, 'success']- ['', 1234, 200, 1, '参数为空']- ['admin', '', 200, 1, '参数为空']
二、pytest记录
conftest.py文件
# coding=utf-8
"""@Project :pachong-master @File :conftest.py@Author :gaojs@Date :2022/6/30 21:47@Blogs : https://www.gaojs.com.cn
"""
from typing import Listimport pytest
import requestsfrom 码同学.requests_study.cookie_study import login@pytest.fixture(scope='session', autouse=True)
def login_and_logout():print('在conftest.py中定义fixture,自动执行')login(userName='admin', password='1234')print('在档次执行测试中只执行一次,因为作用域是session')yieldprint('在当前执行测试只执行一次后置动作,因为作用域是session')# 重写pytest的一个hook函数,处理pycharm插件界面显示的执行结果乱码
def pytest_collection_modifyitems(items:List["item"]):for item in items:item.name = item.name.encode("utf-8").decode("unicode-escape")item._nodeid = item._nodeid.encode("utf-8").decode("unicode-escape")@pytest.fixture(scope='module', autouse=True)
def VPN0():print('在conftest.py中定义fixture,自动执行')login(userName='admin', password='1234')print('在当前每个用例执行一次,因为作用域是module')yieldprint('在当前每个用例执行后执行一次,因为作用域是module')
pytest.ini
不能有中文
[pytest]
addopts = -sv -n auto --dist=loadfiletestpaths = ./python_files = test*.pypython_classes = Test*python_functions = test_*
test_param_caresian.py
# coding=utf-8
"""@Project :pachong-master @File :test_param_login.py@Author :gaojs@Date :2022/6/30 22:44@Blogs : https://www.gaojs.com.cn
"""
import pytest
import requests# 第一步:将测试数据转换成python中列表套列表的格式
from 码同学.requests_study.cookie_study import login
from 码同学.requests_study.put_api_study import post_update_phone_info# 第二:使用pytest装饰器,将其传递给测试用例函数
brand = ['Apple', 'xiaomi', 'sanxing']
color = ['red', 'yellow', 'black']
memorySize = ['256G', '128G', '64G', '512G']
cpuCore=['8核', '4核', '16核']
expect_status_code = [200]
expect_code = ['0']
expect_message = ['更新成功']@pytest.mark.parametrize('brand', brand)
@pytest.mark.parametrize('color', color)
@pytest.mark.parametrize('memorySize', memorySize)
@pytest.mark.parametrize('cpuCore', cpuCore)
@pytest.mark.parametrize('expect_status_code', expect_status_code)
@pytest.mark.parametrize('expect_code', expect_code)
@pytest.mark.parametrize('expect_message', expect_message)
def test_put(brand, color, memorySize, cpuCore, expect_status_code, expect_code, expect_message):"""笛卡尔积参数化:return:"""resp = post_update_phone_info(brand=brand, color=color, memorySize=memorySize, cpuCore=cpuCore)status_code = resp.status_codeassert status_code == expect_status_code# 断言coderesp_json = resp.json()code = resp_json['code']assert code == expect_code# message断言result = resp_json['message']assert result == expect_message# 异常组合不适合笛卡尔积,只能对有效值多个值进行使用
test_param_login.py
# coding=utf-8
"""@Project :pachong-master @File :test_param_login.py@Author :gaojs@Date :2022/6/30 22:44@Blogs : https://www.gaojs.com.cn
"""
import pytest
import requests
from ..datadriver.file_operate import read_yaml, read_excel# 第一步:将测试数据转换成python中列表套列表的格式
from 码同学.requests_study.cookie_study import login# 第一种数据给定:指定在文件中
# test_data = [
# ['admin', '1234', 200, '0', 'success'],
# ['', '1234', 200, '1', '参数为空'],
# ['admin', '', 200, '1', '参数为空']
# ]
# 第二种,通过调用file_operate文件中的方法读取excel数据
# test_data = read_excel(r'E:\爬虫\pachong-master\码同学\datadriver\test_data.xlsx', '数据驱动数据')
test_data = read_yaml(r'E:\爬虫\pachong-master\码同学\datadriver\test_data.yml').get('数据驱动数据')
print(test_data)@pytest.mark.parametrize('userName, password, expect_status_code, expect_code, expect_message', test_data)
def test_login_param(userName, password, expect_status_code, expect_code, expect_message):"""数据驱动:登录测试:return:"""resp = login(userName=userName, password=password)status_code = resp.status_codeassert status_code == expect_status_code# 断言coderesp_json = resp.json()code = resp_json['code']assert code == expect_code# message断言result = resp_json['message']assert result == expect_message
test_by_func.py
# coding=utf-8
"""@Project :pachong-master @File :test_by_func.py@Author :gaojs@Date :2022/6/30 21:55@Blogs : https://www.gaojs.com.cn
"""
# 以函数形式编写测试用例# 测试用例
from 码同学.requests_study.cookie_study import logindef test_login():"""登录测试用例:return:"""resp = login(userName='admin', password='1234')status_code = resp.status_codeassert status_code == 200# 业务断言,resp_json = resp.json()# print(resp_json)code = resp_json['code']assert code == '0'result = resp_json['message']assert result == 'success'def test_login_userisnull():"""登录测试用例:return:"""resp = login(userName='', password='1234')status_code = resp.status_codeassert status_code == 200# 业务断言,resp_json = resp.json()print(resp_json)code = resp_json['code']assert code == '1'result = resp_json['message']assert result == '参数为空'# 运行代码方式
"""
1.运行单个用例
pytest .\码同学\pytest_study\test_by_class.py::TestLogin::test_login_userisnull
2.运行整个类下 的所有用例
pytest -sv .\码同学\pytest_study\test_by_class.py
3.右键执行所有用例:光标放在所有第一个方法顶部4.右键执行某一个用例:贯标放在对应的函数上
"""
test_by_class.py
# coding=utf-8
"""@Project :pachong-master @File :test_by_class.py@Author :gaojs@Date :2022/6/30 21:55@Blogs : https://www.gaojs.com.cn
"""
# 以类形式编写测试用例# 测试用例
from 码同学.requests_study.cookie_study import loginclass TestLogin:# 测试用例1def test_login(self):"""登录测试用例:return:"""resp = login(userName='admin', password='1234')status_code = resp.status_codeassert status_code == 200# 业务断言,resp_json = resp.json()# print(resp_json)code = resp_json['code']assert code == '0'result = resp_json['message']assert result == 'success'# 测试用例2def test_login_userisnull(self):"""登录测试用例:return:"""resp = login(userName='', password='1234')status_code = resp.status_codeassert status_code == 200# 业务断言,resp_json = resp.json()print(resp_json)code = resp_json['code']assert code == '1'result = resp_json['message']assert result == '参数为空'# 运行代码方式
"""
1.运行单个用例
pytest .\码同学\pytest_study\test_by_class.py::TestLogin::test_login_userisnull
2.运行整个类下 的所有用例
pytest -sv .\码同学\pytest_study\test_by_class.py
3.右键执行所有用例
"""
test_preport_function.py
setup_function
# coding=utf-8
"""@Project :pachong-master @File :test_prepost_module.py@Author :gaojs@Date :2022/6/30 22:18@Blogs : https://www.gaojs.com.cn
"""
# 查询余额接口:首先登陆,然后查询,负责提示未登录from 码同学.requests_study.cookie_study import login, querydef setup_function():print('\n************setup_function:在当前脚本文件中,每个用例执行之前,都会执行一次登陆**************')# 登陆接口login(userName='admin', password='1234')def teardown_function():print('***********teardown_function: 在当前脚本文件中,每个测试用例执行后,都会执行一次**************')# 测试用例1:查询余额正确
def test_query():"""正常查询操作:return:"""resp = query(userName='admin')status = resp.status_codeassert status == 200resp_json = resp.json()code = resp_json['code']assert code == '0'result = resp_json['message']assert result == 'success'# 测试用例2:错误的用户名
def test_query_error():"""正常查询操作:return:"""resp = query(userName='gaojs')status = resp.status_codeassert status == 200resp_json = resp.json()code = resp_json['code']assert code == '1'result = resp_json['message']assert result == '用户未登录'
test_prepost_method.py
setup_method
# coding=utf-8
"""@Project :pachong-master @File :test_prepost_module.py@Author :gaojs@Date :2022/6/30 22:18@Blogs : https://www.gaojs.com.cn
"""
# 查询余额接口:首先登陆,然后查询,负责提示未登录
import pytestfrom 码同学.requests_study.cookie_study import login, queryclass TestQuery:def setup_method(self):print('\n************setup_method:在当前类中,每条测试用例执行之前,都会执行一次登陆**************')# 登陆接口login(userName='admin', password='1234')def teardown_method(self):print('***********teardown_method: 在当前类中,每条测试用例执行之后,都会执行一次**************')# 测试用例1:查询余额正确def test_query(self):"""正常查询操作:return:"""resp = query(userName='admin')status = resp.status_codeassert status == 200resp_json = resp.json()code = resp_json['code']assert code == '0'pytest.assume(code == '0', f'实际值:{code},期望值是0')result = resp_json['message']# assert result == 'success'pytest.assume(result == 'success', f'实际值:{result},期望值是success')# 测试用例2:错误的用户名def test_query_error(self):"""正常查询操作:return:"""resp = query(userName='gaojs')status = resp.status_codeassert status == 200resp_json = resp.json()code = resp_json['code']assert code == '1'result = resp_json['message']assert result == '用户未登录'
test_propost_module.py
setup_module
# coding=utf-8
"""@Project :pachong-master @File :test_prepost_module.py@Author :gaojs@Date :2022/6/30 22:18@Blogs : https://www.gaojs.com.cn
"""
# 查询余额接口:首先登陆,然后查询,负责提示未登录from 码同学.requests_study.cookie_study import login, querydef setup_module():print('\n************setup:在当前脚本文件中,所有执测试执行前,只执行一次登陆**************')# 登陆接口login(userName='admin', password='1234')def teardown_module():print('***********teardown: 在当前脚本文件中,所有执测试执行后,只执行一次**************')# 测试用例1:查询余额正确
def test_query():"""正常查询操作:return:"""resp = query(userName='admin')status = resp.status_codeassert status == 200resp_json = resp.json()code = resp_json['code']assert code == '0'result = resp_json['message']assert result == 'success'# 测试用例2:错误的用户名
def test_query_error():"""正常查询操作:return:"""resp = query(userName='gaojs')status = resp.status_codeassert status == 200resp_json = resp.json()code = resp_json['code']assert code == '1'result = resp_json['message']assert result == '用户未登录'
test_prepost_class.py
# coding=utf-8
"""@Project :pachong-master @File :test_prepost_module.py@Author :gaojs@Date :2022/6/30 22:18@Blogs : https://www.gaojs.com.cn
"""
# 查询余额接口:首先登陆,然后查询,负责提示未登录
import pytestfrom 码同学.requests_study.cookie_study import login, query# @pytest.fixture(scope='class', autouse=True)
# def login_and_logout():
# print('\n************setup_class:在当前类中,在每个类执行之前,都会执行一次登陆**************')
# login()
# yield
# print('***********teardown_class: 在当前类中,在每个类执行之后,都会执行一次**************')class TestQuery:# def setup_class(self):# print('\n************setup_class:在当前类中,在每个类执行之前,都会执行一次登陆**************')# # 登陆接口# login(userName='admin', password='1234')## def teardown_class(self):# print('***********teardown_class: 在当前类中,在每个类执行之后,都会执行一次**************')# 测试用例1:查询余额正确def test_query(self, login_and_logout):"""正常查询操作:return:"""resp = query(userName='admin')status = resp.status_codeassert status == 200resp_json = resp.json()code = resp_json['code']assert code == '0'result = resp_json['message']assert result == 'success'# 测试用例2:错误的用户名def test_query_error(self, login_and_logout):"""正常查询操作:return:"""resp = query(userName='gaojs')status = resp.status_codeassert status == 200resp_json = resp.json()code = resp_json['code']assert code == '1'result = resp_json['message']assert result == '用户未登录'class TestQuery1:# 测试用例1:查询余额正确def test_query1(self, login_and_logout):"""正常查询操作:return:"""resp = query(userName='admin')status = resp.status_codeassert status == 200resp_json = resp.json()code = resp_json['code']assert code == '0'result = resp_json['message']assert result == 'success'# 测试用例2:错误的用户名def test_query_error1(self, login_and_logout):"""正常查询操作:return:"""resp = query(userName='gaojs')status = resp.status_codeassert status == 200resp_json = resp.json()code = resp_json['code']assert code == '1'result = resp_json['message']assert result == '用户未登录'
readME文件
总结:
1.模块级别最大,因为不管是函数式测试用例,还是类方式的测试用例,都在一个模块中
2.函数级别仅仅是针对,函数式测试用例生效(setup_function()不能再类方式中使用,类方式中要使用setup_method())
3.类级别和方法级别,是针对于类方式编写的测试用例生效
4.setup和teardown是可以替换函数级别和方法级别的前置后置1.运行单个用例
pytest .\码同学\pytest_study\test_by_class.py::TestLogin::test_login_userisnull
2.运行整个类下 的所有用例
pytest -sv .\码同学\pytest_study\test_by_class.py
3.右键执行所有用例:光标放在所有第一个方法顶部4.右键执行某一个用例:贯标放在对应的函数上异常组合不适合笛卡尔积,只能对有效值多个值进行使用
三、requests记录
cookie_study.py
# coding=utf-8
"""@Project :pachong-master @File :cookie_study.py@Author :gaojs@Date :2022/6/28 22:50@Blogs : https://www.gaojs.com.cn
"""
import requests# 多个接口使用同一个session对象的话,他会自动的帮我们去管理和关联cookie
session = requests.session()def login(userName='admin', password='1234'):"""登录操作:return:"""url = 'http://localhost:9090/bank/api/login'data = {'userName': userName,'password': password}rsp = session.post(url=url, data=data)result = rsp.json().get('message')return rspdef query(userName='admin'):"""银行余额查询接口:return:"""url = 'http://localhost:9090/bank/api/query'params = {'userName': userName}rsp = session.get(url=url, params=params)print(rsp.text)result = rsp.json().get('message')print(result)money_data = rsp.json().get('data')print(money_data)return rsplogin()
query()
delete_api.py
# coding=utf-8
"""@Project :pachong-master @File :delete_api_study.py@Author :gaojs@Date :2022/6/28 23:26@Blogs : https://www.gaojs.com.cn
"""
import requestsdef delete_phone_info():"""put请求更新手机信息:return:"""url = 'http://localhost:9090/com/phone'data = {"brand": "Apple", "color": "red","memorySize": "256G", "cpuCore": "8核","price": "10080", "desc": "全新上市"}rsp = requests.delete(url=url, json=data)print(rsp.text)result = rsp.json().get('message')print(result)
file_upload.py
# coding=utf-8
"""@Project :pachong-master @File :file_upload_study.py@Author :gaojs@Date :2022/6/28 23:17@Blogs : https://www.gaojs.com.cn
"""
import requestssession = requests.session()def file_upload():"""上传文件:return:"""url = 'http://localhost:9090/file/api/upload2'file = {'file': open(r'C:\Users\Administrator\Desktop\123.jpg', mode='rb')}rsp = session.post(url=url, files=file)result = rsp.json().get('message')print(result)if __name__ == '__main__':file_upload()
post_api.py
# coding=utf-8
"""@Project :pachong-master @File :post_api_study.py@Author :gaojs@Date :2022/6/28 22:43@Blogs : https://www.gaojs.com.cn
"""
import requestsdef post_api():"""post请求:return:"""url = 'http://localhost:9090/com/login'data = {'userName': 'admin','password': '1234'}rsp = requests.post(url=url, data=data)result = rsp.json().get('message')print(result)def post_add_phone_info():"""新增手机信息:return:"""url = 'http://localhost:9090/com/phone'data = {"brand": "Huawei", "color": "yellow","memorySize": "64G", "cpuCore": "8核","price": "8848", "desc": "全新上市"}rsp = requests.post(url=url, json=data)result = rsp.json().get('message')print(result)
put_api.py
# coding=utf-8
"""@Project :pachong-master @File :put_api_study.py@Author :gaojs@Date :2022/6/28 22:49@Blogs : https://www.gaojs.com.cn
"""
import requestsdef post_update_phone_info(brand='Apple', color='red', memorySize='256G', cpuCore='8核'):"""put请求更新手机信息:return:"""url = 'http://localhost:9090/com/phone'data = {"brand": brand,"color": color,"memorySize": memorySize,"cpuCore": cpuCore,"price": "10080","desc": "全新上市"}rsp = requests.put(url=url, json=data)result = rsp.json().get('message')print(result)return rsppost_update_phone_info()
token_study.py
# coding=utf-8
"""@Project :pachong-master @File :token_study.py@Author :gaojs@Date :2022/6/28 23:01@Blogs : https://www.gaojs.com.cn
"""
import requestssession = requests.session()def login(userName='admin', password='1234'):"""获取token:return:"""url = 'http://localhost:9090/bank/api/login2'data = {'userName': userName,'password': password}rsp = session.post(url=url, data=data)print(rsp.text)return rspdef post_api_token(userName='admin', password='1234'):"""获取token:return:"""url = 'http://localhost:9090/bank/api/login2'data = {'userName': userName,'password': password}rsp = session.post(url=url, data=data)print(rsp.text)msg = rsp.json().get('message')print(msg)global tokentoken = rsp.json().get('data')print(token)return tokendef query_money():"""银行余额查询接口:return:"""url = 'http://localhost:9090/bank/api/query2'params = {'userName': 'admin'}headers = {'testfan-token': token}rsp = session.get(url=url, headers=headers, params=params)print(rsp.text)result = rsp.json().get('data')print(result)if __name__ == '__main__':post_api_token()query_money()
readME
总结:
requests库的请求方法参数众多,划分如下:global全局参数使用:不通的函数中如果想使用的话就用global查询参数就用params=params
表单参数就用data=data
json参数就用json=json
文件参数就用files=files
请求头信息headers就用headers=headers
pytest数据驱动及conftest文件及装饰器使用相关推荐
- 【单元测试】pytest:配置|断言|参数化|夹具|装饰器|插件
[单元测试]pytest 入门案例 pytest配置文件 断言 参数化 夹具 模块级 类级 方法级 函数级 fixture装饰器 插件 unittest:python自带的单元测试框架,兼容性好 py ...
- python文件下载速度 装饰器_python学习笔记之---装饰器
# -*- coding:utf-8 -*- '''示例1: 最简单的函数,表示调用了两次''' def myfunc(): print ("myfunc() called.") ...
- python文件下载速度 装饰器_python使用装饰器对文件进行读写操作'及遍历文件目录...
'''使用装饰器对文件进行读写操作''' #def check_permission(func):#'''演示嵌套函数定义及使用'''#def wrapper(*args,**kwargs):#''' ...
- 【Pytest+Allure】pytest+allure自学轨迹1--认识pytest和pytest的装饰器
认识pytest和pytest的装饰器 认识pytest pytest的装饰器 使用pytest 安装与导入 pytest用例的写法 使用fixture装饰器 作用域 不指定作用域(默认作用域func ...
- Python pytest框架之@pytest.fixture()和conftest详解
一.fixture简介 学pytest就不得不说fixture,fixture是pytest的精髓所在,类似unittest中setup/teardown这种前后置东西.但是比它们要强大.灵活很多,它 ...
- Python装饰器学习笔记
Python装饰器 文章目录 Python装饰器 基本概念 从零开始的逐步分析 修饰后的问题 向被包装后的函数传递参数 使用场景:stdout日志 接受参数的装饰器 作为一个类的装饰器 总结 学习资料 ...
- 装饰器python3菜鸟教程_认识Python装饰器
Python中的装饰器用来给Python中的函数添加一些辅助功能.比如我们可以把[输出日志]这个辅助功能写到一个装饰器里.只要我们在某个函数A之前添加了这个[输出日志]的装饰器,那么执行函数A的时候, ...
- 软件测试 pytest pytest的命名规则 用例的前后置 conftest.py 定制allure报告 @pytest.mark.parametrize()装饰器作数据驱动
文章目录 1 pytest简介 1.1 pytest的命名规则 1.2 运行方式 1.2.1 主函数方式(少用) 1.2.2 命令行方式(少用) 1.2.3 pytest.ini的配置文件方式(最经常 ...
- Python Pytest装饰器@pytest.mark.parametrize用例数据驱动(三)
一.测试用例用excel管理,存放地址:C:\Users\wangli\PycharmProjects\Test\test\files\apiCase.xls 二.代码实现如下: 1.封装读取exce ...
最新文章
- android wear无法启用,android-wear – 无法创建Android虚拟设备,“没有为此目标安装系统映像”...
- Appium环境安装
- TensorFlow Serving + Docker + Tornado机器学习模型生产级快速部署
- list赋值给另一个list_Python小知识: List的赋值方法,不能直接等于
- STC单片机程序下载失败总结
- C#利用SQLDMO备份与还原数据库
- 幼儿园小班上计算机课 作业内容是手口一致,小班幼儿手口不能一致的点数怎么办...
- python中字典按键或键值排序_[宜配屋]听图阁
- xlsx文件打开乱码_excel表格文件打开都是乱码怎么解决
- 【通信协议学习】关于Xmodem、Ymodem、Zmodem、ASCII、Binary传输协议
- java如何统计txt的字数_Java HashSet对txt文本内容去重(统计小说用过的字或字数)...
- 信号调制三种方法的带宽比较
- c语言错误1083,没有混音设备可用,启动Windows Audio服务时错误1083
- 【FICO】标准成本、计划成本、实际成本、目标成本
- 生活在深圳我们需要的不是叹息与感概
- 用于传感器互操作性问题的指纹匹配系统的大规模研究
- Canvas如何等待所有图片加载完成才开始绘图
- java按键发出声音代码_用Java写的一个根据按键发声的程序,为什么只有前16次按键响...
- “大数据杀熟”谁之祸?
- 记忆存储程序使得计算机能够实现,2016年职称计算机考试模块综合试题及答案(4)...
热门文章
- 什么是:VGA SVGA XGA SXGA
- 一个计算机几个用户登录,一台电脑登录多个头条账号的方法,用这个软件很方便!...
- 帮G1刷新的hboot和radio
- win7安装Microsoft Visial C++2015 Redistributable提示:无法建立到信任根
- linux如何运行windows游戏,cedega - Ubuntu下也玩Windows游戏,三种途径开启魔兽[图文]_Linux教程_Linux公社-Linux系统门户网站...
- 前端简介,head内标签
- WireShark 简介
- 无公网IP?教你在外远程访问本地wamp服务器「内网穿透」
- Matlab学习-CDF(累积分布函数图)绘制
- EasyX的下载与使用教程网址