From 46ce8ddc6b731ec1db8b5724ad90a3aa2eb48e43 Mon Sep 17 00:00:00 2001 From: zy7y <13271962515@163.com> Date: Thu, 19 Nov 2020 00:49:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0path=E5=8F=82=E6=95=B0?= =?UTF-8?q?=EF=BC=8C=E8=AF=B7=E6=B1=82=E5=8F=82=E6=95=B0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E5=A4=84=E7=90=86=E6=96=B9=E5=BC=8F=EF=BC=8C?= =?UTF-8?q?=E5=87=8F=E5=B0=91=E5=86=97=E4=BD=99=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +- api/base_requests.py | 18 +-- config/config.yaml | 5 +- data/case_data.xlsx | Bin 27648 -> 27648 bytes test/__init__.py | 4 +- test/test_api.py | 31 +++-- tools/__init__.py | 19 ++- tools/data_process.py | 277 ++++++++++++++++++++++++++++++++++++++++++ tools/read_data.py | 20 +-- 9 files changed, 335 insertions(+), 44 deletions(-) create mode 100644 tools/data_process.py diff --git a/README.md b/README.md index 71b6457..1dc3dbe 100644 --- a/README.md +++ b/README.md @@ -57,13 +57,12 @@ >> >> >`__init__.py` >> > ->> >data_tearing.py:封装依赖数据与请求数据的逻辑处理,处理了path参数依赖,headers关键字参数的入参header +>> >data_process.py:封装依赖数据与请求数据的逻辑处理,处理了path参数依赖,headers关键字参数的入参header >> > >> >read_config.py: 读取配置文件 >> > >> >read_data.py: 读取excel用例文件 >> > ->> >save_response.py: 保存实际响应结果,处理依赖数据提取 >> > >> >send_email.py : 发送邮件 >> > @@ -71,7 +70,6 @@ >> >> venv: python 虚拟环境 >> ->> apiAutoTest用例说明.md: excel用例书写规则 >> >> pytest.ini: pytest框架的一个可用配置,解决中文显示乱码 >> @@ -117,6 +115,7 @@ https://www.bilibili.com/video/BV1EE411B7SU?p=10 #### 更新 2020/08/08 增加实际响应存储数据的方法,并在字典可以处理依赖见tools/svae_response.py 2020/08/09 实现多文件上传,接口中Path参数依赖处理 +2020/11/18 使用re库解决当请求参数层级结构多出现无法提取的bug,减少冗余代码,优化path路径参数提取,更新用例填写说明文档 #### 博客园首发 https://www.cnblogs.com/zy7y/p/13426816.html diff --git a/api/base_requests.py b/api/base_requests.py index dab6c4e..8771bfa 100644 --- a/api/base_requests.py +++ b/api/base_requests.py @@ -10,15 +10,17 @@ from loguru import logger import requests +from tools.read_data import ReadData + class BaseRequest(object): def __init__(self): - # 修改时间:2020年9月14日17:09 - # 确保,整个接口测试中,使用同一个requests.Session() 来管理cookie + # 修改时间:2020年9月14日17:09 + # 确保,整个接口测试中,使用同一个requests.Session() 来管理cookie self.session = requests.Session() # 请求 - def base_requests(self, method, url, parametric_key=None, data=None, file_var=None, file_path=None, header=None): + def send_requests(self, method, url, parametric_key=None, data=None, file_var=None, file_path=None, header=None): """ :param method: 请求方法 @@ -35,6 +37,7 @@ class BaseRequest(object): """ # 修改时间:2020年9月14日17:09 session = self.session + if (file_var in [None, '']) and (file_path in [None, '']): files = None else: @@ -48,7 +51,6 @@ class BaseRequest(object): else: # 单文件上传 files = {file_var: open(file_path, 'rb')} - if parametric_key == 'params': res = session.request(method=method, url=url, params=data, headers=header) elif parametric_key == 'data': @@ -56,9 +58,7 @@ class BaseRequest(object): elif parametric_key == 'json': res = session.request(method=method, url=url, json=data, files=files, headers=header) else: - raise ValueError('可选关键字为:get/delete/head/options/请求使用params, post/put/patch请求可使用json(application/json)/data') + raise ValueError( + '可选关键字为:get/delete/head/options/请求使用params, post/put/patch请求可使用json(application/json)/data') logger.info(f'请求方法:{method},请求路径:{url}, 请求参数:{data}, 请求文件:{files}, 请求头:{header})') - return res.json() - - - + return res.json() \ No newline at end of file diff --git a/config/config.yaml b/config/config.yaml index 24c6d09..abdad31 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -1,7 +1,8 @@ server: test: http://127.0.0.1:8888/api/private/v1/ - # 实例代码使用的接口服务,已改为作者是自己的云服务器部署。(后端源码来自b站:https://www.bilibili.com/video/BV1EE411B7SU?p=10) - dev: http://49.232.203.244:8888/api/private/v1/ + # https://space.bilibili.com/283273603 演示项目后端服务来自 + dev: http://www.ysqorz.top:8888/api/private/v1/ + # 实际响应jsonpath提取规则设置 response_reg: diff --git a/data/case_data.xlsx b/data/case_data.xlsx index 720affe1365fbe8e1d02cb62fa250941fb8c572c..297f3d5fb91ab423ccb76fbbbb65d781df6d8d5f 100644 GIT binary patch delta 6342 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 delta 6338 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 diff --git a/test/__init__.py b/test/__init__.py index 93afd8a..9534fd8 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -6,6 +6,4 @@ @file: __init__.py.py @ide: PyCharm @time: 2020/7/31 -""" - -from loguru import logger \ No newline at end of file +""" \ No newline at end of file diff --git a/test/test_api.py b/test/test_api.py index 4bb2474..537ae45 100644 --- a/test/test_api.py +++ b/test/test_api.py @@ -13,27 +13,20 @@ from loguru import logger import pytest import allure from api.base_requests import BaseRequest -from tools.data_tearing import TreatingData +from tools.data_process import DataProcess from tools.read_config import ReadConfig from tools.read_data import ReadData -from tools.save_response import SaveResponse # 读取配置文件 对象 rc = ReadConfig() base_url = rc.read_serve_config('dev') token_reg, res_reg = rc.read_response_reg() -case_data_path = rc.read_file_path('case_data') report_data = rc.read_file_path('report_data') report_generate = rc.read_file_path('report_generate') log_path = rc.read_file_path('log_path') -report_zip = rc.read_file_path('report_zip') email_setting = rc.read_email_setting() -# 实例化存响应的对象 -save_response_dict = SaveResponse() # 读取excel数据对象 -data_list = ReadData(case_data_path).get_data() -# 数据处理对象 -treat_data = TreatingData() +data_list = ReadData.get_data() # 请求对象 br = BaseRequest() logger.info(f'配置文件/excel数据/对象实例化,等前置条件处理完毕\n\n') @@ -57,9 +50,9 @@ class TestApiAuto(object): logger.warning('报告已生成') @pytest.mark.parametrize('case_number,case_title,path,is_token,method,parametric_key,file_var,' - 'file_path, parameters, dependent,data,expect', data_list) + 'file_path,data,expect', data_list) def test_main(self, case_number, case_title, path, is_token, method, parametric_key, file_var, - file_path, parameters, dependent, data, expect): + file_path, data, expect): # 感谢:https://www.cnblogs.com/yoyoketang/p/13386145.html,提供动态添加标题的实例代码 # 动态添加标题 @@ -67,24 +60,28 @@ class TestApiAuto(object): logger.debug(f'⬇️⬇️⬇️...执行用例编号:{case_number}...⬇️⬇️⬇️️') with allure.step("处理相关数据依赖,header"): - data, header, parameters_path_url = treat_data.treating_data(is_token, parameters, dependent, data, save_response_dict) + + header = DataProcess.header allure.attach(json.dumps(header, ensure_ascii=False, indent=4), "请求头", allure.attachment_type.TEXT) + path = DataProcess.handle_path(path) + + data = DataProcess.handle_data(data) allure.attach(json.dumps(data, ensure_ascii=False, indent=4), "请求数据", allure.attachment_type.TEXT) with allure.step("发送请求,取得响应结果的json串"): - allure.attach(json.dumps(base_url + path + parameters_path_url, ensure_ascii=False, indent=4), "最终请求地址", allure.attachment_type.TEXT) - res = br.base_requests(method=method, url=base_url + path + parameters_path_url, parametric_key=parametric_key, file_var=file_var, file_path=file_path, + allure.attach(json.dumps(base_url + path, ensure_ascii=False, indent=4), "最终请求地址", allure.attachment_type.TEXT) + res = br.send_requests(method=method, url=base_url + path, parametric_key=parametric_key, file_var=file_var, file_path=file_path, data=data, header=header) allure.attach(json.dumps(res, ensure_ascii=False, indent=4), "实际响应", allure.attachment_type.TEXT) with allure.step("将响应结果的内容写入实际响应字典中"): - save_response_dict.save_actual_response(case_key=case_number, case_response=res) - allure.attach(json.dumps(save_response_dict.actual_response, ensure_ascii=False, indent=4), "实际响应字典", allure.attachment_type.TEXT) + DataProcess.save_response(case_number, res) + allure.attach(json.dumps(DataProcess.response_dict, ensure_ascii=False, indent=4), "实际响应字典", allure.attachment_type.TEXT) # 写token的接口必须是要正确无误能返回token的 if is_token == '写': with allure.step("从登录后的响应中提取token到header中"): - treat_data.token_header['Authorization'] = jsonpath.jsonpath(res, token_reg)[0] + DataProcess.handle_header(is_token, res, token_reg) with allure.step("根据配置文件的提取响应规则提取实际数据"): really = jsonpath.jsonpath(res, res_reg)[0] diff --git a/tools/__init__.py b/tools/__init__.py index 9534fd8..e4cd5e0 100644 --- a/tools/__init__.py +++ b/tools/__init__.py @@ -6,4 +6,21 @@ @file: __init__.py.py @ide: PyCharm @time: 2020/7/31 -""" \ No newline at end of file +""" +from jsonpath import jsonpath +from loguru import logger + + +def extractor(obj: dict, expr: str = '.') -> object: + """ + :param obj :json/dict类型数据 + :param expr: 表达式, . 提取字典所有内容, $.case 提取一级字典case, $.case.data 提取case字典下的data + $.0.1 提取字典中的第一个列表中的第二个的值 + """ + try: + result = jsonpath(obj, expr)[0] + except Exception as e: + logger.error(f'提取不到内容,丢给你一个错误!{e}') + result = None + return result + diff --git a/tools/data_process.py b/tools/data_process.py new file mode 100644 index 0000000..7bd6b1f --- /dev/null +++ b/tools/data_process.py @@ -0,0 +1,277 @@ +#!/usr/bin/env/python3 +# -*- coding:utf-8 -*- +""" +@project: apiAutoTest +@author: zy7y +@file: data_process.py +@ide: PyCharm +@time: 2020/11/18 +""" +import json +import re +from tools import * +from tools.read_config import ReadConfig + + +class DataProcess: + response_dict = {} + header = {} + null_header = {} + + @classmethod + def save_response(cls, key: str, value: object) -> None: + """ + 保存实际响应 + :param key: 保存字典中的key,一般使用用例编号 + :param value: 保存字典中的value,使用json响应 + """ + cls.response_dict[key] = value + logger.info(f'添加key: {key}, 对应value: {value}') + + @classmethod + def handle_path(cls, path_str: str = '') -> str: + """路径参数处理 + :param path_str: 带提取表达式的字符串 /&$.case_005.data.id&/state/&$.case_005.data.create_time& + 上述内容表示,从响应字典中提取到case_005字典里data字典里id的值,假设是500,后面&$.case_005.data.create_time& 类似,最终提取结果 + return /511/state/1605711095 + """ + # /&$.case.data.id&/state/&$.case_005.data.create_time& + path_str.split('/') + for i in re.findall('&(.*?)&', path_str): + path_str = path_str.replace(f'&{i}&', str(extractor(cls.response_dict, i))) + logger.info(f'提取出的路径地址: {path_str}') + return path_str + + @classmethod + def handle_header(cls, is_token: str, response: dict, reg) -> dict: + """处理header""" + if is_token == '写': + cls.header['Authorization'] = extractor(response, reg) + return cls.header + elif is_token == '': + return cls.null_header + else: + return cls.header + + @classmethod + def handle_data(cls, variable: str) -> dict: + """请求数据处理 + :param variable: 请求数据,传入的是可转换字典/json的字符串,其中可以包含变量表达式 + return 处理之后的json/dict类型的字典数据 + """ + if variable == '': + return + for i in re.findall('&(.*?)&', variable): + variable = variable.replace(f'&{i}&', str(extractor(cls.response_dict, i))) + if 'null' in variable: + variable = variable.replace('null', 'None') + if 'true' in variable: + variable = variable.replace('true', 'True') + if 'false' in variable: + variable = variable.replace('false', 'False') + logger.info(f'最终的请求数据如下: {variable}') + print(variable) + return eval(variable) + + + +if __name__ == '__main__': + data = """{ + "case_001": { + "data": null, + "meta": { + "msg": "参数错误", + "status": 400 + } + }, + "case_002": { + "data": { + "id": 500, + "rid": 0, + "username": "admin", + "mobile": "12345678", + "email": "adsfad@qq.com", + "token": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjUwMCwicmlkIjowLCJpYXQiOjE2MDU3MTEwOTUsImV4cCI6MTYwNTc5NzQ5NX0.v4YsivyRT9I0kFnIIph7btKdTg7SfeeO6xsbhrGJC5w" + }, + "meta": { + "msg": "登录成功", + "status": 200 + } + }, + "case_003": { + "data": { + "total": 5, + "pagenum": 1, + "users": [ + { + "id": 500, + "role_name": "超级管理员", + "username": "admin", + "create_time": 1486720211, + "mobile": "12345678", + "email": "adsfad@qq.com", + "mg_state": true + }, + { + "id": 502, + "role_name": "测试角色2", + "username": "linken", + "create_time": 1486720211, + "mobile": "1213213123", + "email": "asdf@qq.com", + "mg_state": false + }, + { + "id": 508, + "role_name": "主管", + "username": "asdf1", + "create_time": 1511853015, + "mobile": "123123", + "email": "adfsa@qq.com", + "mg_state": true + }, + { + "id": 509, + "role_name": "test", + "username": "asdf123", + "create_time": 1511853353, + "mobile": "1111", + "email": "asdf@qq.com", + "mg_state": false + }, + { + "id": 510, + "role_name": "超级管理员", + "username": "小明111", + "create_time": 1605710570, + "mobile": "13288888888", + "email": "1232@qq.com", + "mg_state": false + } + ] + }, + "meta": { + "msg": "获取管理员列表成功", + "status": 200 + } + }, + "case_004": { + "data": null, + "meta": { + "msg": "无效token", + "status": 400 + } + }, + "case_005": { + "data": { + "id": 511, + "username": "tester_zy7y1213", + "role_id": -1, + "create_time": 1605711095 + }, + "meta": { + "msg": "创建成功", + "status": 201 + } + }, + "case_006": { + "data": { + "id": 511, + "rid": -1, + "username": "tester_zy7y1213", + "mobile": null, + "email": null, + "mg_state": 0 + }, + "meta": { + "msg": "设置状态成功", + "status": 200 + } + }, + "case_007": { + "data": { + "id": 511, + "rid": -1, + "username": "tester_zy7y1213", + "mobile": null, + "email": null, + "mg_state": 0 + }, + "meta": { + "msg": "设置状态成功", + "status": 200 + } + }, + "case_008": { + "data": null, + "meta": { + "msg": "删除成功", + "status": 200 + } + }, + "case_009": { + "data": { + "total": 5, + "pagenum": 1, + "users": [ + { + "id": 500, + "role_name": "超级管理员", + "username": "admin", + "create_time": 1486720211, + "mobile": "12345678", + "email": "adsfad@qq.com", + "mg_state": true + }, + { + "id": 502, + "role_name": "测试角色2", + "username": "linken", + "create_time": 1486720211, + "mobile": "1213213123", + "email": "asdf@qq.com", + "mg_state": false + }, + { + "id": 508, + "role_name": "主管", + "username": "asdf1", + "create_time": 1511853015, + "mobile": "123123", + "email": "adfsa@qq.com", + "mg_state": true + }, + { + "id": 509, + "role_name": "test", + "username": "asdf123", + "create_time": 1511853353, + "mobile": "1111", + "email": "asdf@qq.com", + "mg_state": false + }, + { + "id": 510, + "role_name": "超级管理员", + "username": "小明111", + "create_time": 1605710570, + "mobile": "13288888888", + "email": "1232@qq.com", + "mg_state": false + } + ] + }, + "meta": { + "msg": "获取管理员列表成功", + "status": 200 + } + } +}""" + DataProcess.response_dict = json.loads(data) + print(DataProcess.response_dict, type(DataProcess.response_dict)) + + ds = "$.case_001.meta, $.case_001.data, $.case_003.data.users.0.mobile" + + varb = "{'name': 'zy7y', 'meta': &$.case_001.meta&, 'dd': '&$.case_003.data.users.0.mobile&'}" + print(DataProcess.handle_data(varb, ds), type(DataProcess.handle_data(varb, ds))) + print(DataProcess.handle_path('/&$.case_005.data.id&/state/&$.case_005.data.create_time&')) diff --git a/tools/read_data.py b/tools/read_data.py index 27da5de..d05766f 100644 --- a/tools/read_data.py +++ b/tools/read_data.py @@ -8,28 +8,30 @@ @time: 2020/7/31 """ import xlrd -from test import logger +from tools import * class ReadData(object): - def __init__(self, excel_path): - self.excel_file = excel_path - self.book = xlrd.open_workbook(self.excel_file) + excel_path = '../data/case_data.xlsx' - def get_data(self): + @classmethod + def get_data(cls): """ :return: data_list - pytest参数化可用的数据 """ data_list = [] - table = self.book.sheet_by_index(0) + book = xlrd.open_workbook(cls.excel_path) + table = book.sheet_by_index(0) for norw in range(1, table.nrows): # 每行第4列 是否运行 if table.cell_value(norw, 3) != '否': # 每行第三列等于否将不读取内容 value = table.row_values(norw) value.pop(3) - # 配合将每一行转换成元组存储,迎合 pytest的参数化操作,如不需要可以注释掉 value = tuple(value) - value = tuple(value) logger.info(f'{value}') - data_list.append(value) + data_list.append(list(value)) return data_list + + +if __name__ == '__main__': + ReadData.get_data() \ No newline at end of file