pytest-auto-api2-cli 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cli.py +9 -0
- common/__init__.py +0 -0
- common/setting.py +78 -0
- pytest_auto_api2/__init__.py +4 -0
- pytest_auto_api2/cli.py +900 -0
- pytest_auto_api2/runtime/__init__.py +1 -0
- pytest_auto_api2/runtime/api.py +10 -0
- pytest_auto_api2/runtime/loader.py +80 -0
- pytest_auto_api2_cli-0.2.0.dist-info/METADATA +945 -0
- pytest_auto_api2_cli-0.2.0.dist-info/RECORD +73 -0
- pytest_auto_api2_cli-0.2.0.dist-info/WHEEL +5 -0
- pytest_auto_api2_cli-0.2.0.dist-info/entry_points.txt +2 -0
- pytest_auto_api2_cli-0.2.0.dist-info/top_level.txt +6 -0
- run.py +85 -0
- test_case/Collect/test_collect_addtool.py +40 -0
- test_case/Collect/test_collect_delete_tool.py +40 -0
- test_case/Collect/test_collect_tool_list.py +40 -0
- test_case/Collect/test_collect_update_tool.py +40 -0
- test_case/Login/test_login.py +40 -0
- test_case/UserInfo/test_get_user_info.py +40 -0
- test_case/__init__.py +6 -0
- test_case/conftest.py +132 -0
- utils/__init__.py +9 -0
- utils/assertion/__init__.py +4 -0
- utils/assertion/assert_control.py +179 -0
- utils/assertion/assert_type.py +141 -0
- utils/cache_process/__init__.py +4 -0
- utils/cache_process/cache_control.py +89 -0
- utils/cache_process/redis_control.py +106 -0
- utils/logging_tool/__init__.py +4 -0
- utils/logging_tool/log_control.py +84 -0
- utils/logging_tool/log_decorator.py +48 -0
- utils/logging_tool/run_time_decorator.py +34 -0
- utils/mysql_tool/__init__.py +4 -0
- utils/mysql_tool/mysql_control.py +175 -0
- utils/notify/__init__.py +1 -0
- utils/notify/ding_talk.py +153 -0
- utils/notify/lark.py +181 -0
- utils/notify/send_mail.py +84 -0
- utils/notify/wechat_send.py +109 -0
- utils/other_tools/__init__.py +0 -0
- utils/other_tools/address_detection.py +73 -0
- utils/other_tools/allure_data/__init__.py +4 -0
- utils/other_tools/allure_data/allure_report_data.py +84 -0
- utils/other_tools/allure_data/allure_tools.py +54 -0
- utils/other_tools/allure_data/error_case_excel.py +316 -0
- utils/other_tools/exceptions.py +47 -0
- utils/other_tools/get_local_ip.py +27 -0
- utils/other_tools/install_tool/__init__.py +0 -0
- utils/other_tools/install_tool/install_requirements.py +91 -0
- utils/other_tools/jsonpath_date_replace.py +28 -0
- utils/other_tools/models.py +269 -0
- utils/other_tools/thread_tool.py +91 -0
- utils/read_files_tools/__init__.py +1 -0
- utils/read_files_tools/case_automatic_control.py +138 -0
- utils/read_files_tools/clean_files.py +19 -0
- utils/read_files_tools/excel_control.py +55 -0
- utils/read_files_tools/get_all_files_path.py +27 -0
- utils/read_files_tools/get_yaml_data_analysis.py +156 -0
- utils/read_files_tools/regular_control.py +209 -0
- utils/read_files_tools/swagger_for_yaml.py +145 -0
- utils/read_files_tools/testcase_template.py +103 -0
- utils/read_files_tools/yaml_control.py +86 -0
- utils/recording/__init__.py +0 -0
- utils/recording/mitmproxy_control.py +225 -0
- utils/requests_tool/__init__.py +0 -0
- utils/requests_tool/dependent_case.py +273 -0
- utils/requests_tool/encryption_algorithm_control.py +80 -0
- utils/requests_tool/request_control.py +443 -0
- utils/requests_tool/set_current_request_cache.py +73 -0
- utils/requests_tool/teardown_control.py +280 -0
- utils/times_tool/__init__.py +0 -0
- utils/times_tool/time_control.py +87 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
# @Time : 2022/3/28 12:52
|
|
5
|
+
# @Author : 余少琪
|
|
6
|
+
"""
|
|
7
|
+
import ast
|
|
8
|
+
import os
|
|
9
|
+
import random
|
|
10
|
+
import time
|
|
11
|
+
import urllib
|
|
12
|
+
from typing import Tuple, Dict, Union, Text
|
|
13
|
+
import requests
|
|
14
|
+
import urllib3
|
|
15
|
+
from requests_toolbelt import MultipartEncoder
|
|
16
|
+
from common.setting import ensure_path_sep
|
|
17
|
+
from utils.other_tools.models import RequestType
|
|
18
|
+
from utils.logging_tool.log_decorator import log_decorator
|
|
19
|
+
from utils.mysql_tool.mysql_control import AssertExecution
|
|
20
|
+
from utils.logging_tool.run_time_decorator import execution_duration
|
|
21
|
+
from utils.other_tools.allure_data.allure_tools import allure_step, allure_step_no, allure_attach
|
|
22
|
+
from utils.read_files_tools.regular_control import cache_regular
|
|
23
|
+
from utils.requests_tool.set_current_request_cache import SetCurrentRequestCache
|
|
24
|
+
from utils.other_tools.models import TestCase, ResponseData
|
|
25
|
+
from utils import config
|
|
26
|
+
# from utils.requests_tool.encryption_algorithm_control import encryption
|
|
27
|
+
|
|
28
|
+
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class RequestControl:
|
|
32
|
+
""" 封装请求 """
|
|
33
|
+
|
|
34
|
+
def __init__(self, yaml_case):
|
|
35
|
+
self.__yaml_case = TestCase(**yaml_case)
|
|
36
|
+
|
|
37
|
+
def file_data_exit(
|
|
38
|
+
self,
|
|
39
|
+
file_data) -> None:
|
|
40
|
+
"""判断上传文件时,data参数是否存在"""
|
|
41
|
+
# 兼容又要上传文件,又要上传其他类型参数
|
|
42
|
+
try:
|
|
43
|
+
_data = self.__yaml_case.data
|
|
44
|
+
for key, value in ast.literal_eval(cache_regular(str(_data)))['data'].items():
|
|
45
|
+
if "multipart/form-data" in str(self.__yaml_case.headers.values()):
|
|
46
|
+
file_data[key] = str(value)
|
|
47
|
+
else:
|
|
48
|
+
file_data[key] = value
|
|
49
|
+
except KeyError:
|
|
50
|
+
...
|
|
51
|
+
|
|
52
|
+
@classmethod
|
|
53
|
+
def multipart_data(
|
|
54
|
+
cls,
|
|
55
|
+
file_data: Dict):
|
|
56
|
+
""" 处理上传文件数据 """
|
|
57
|
+
multipart = MultipartEncoder(
|
|
58
|
+
fields=file_data, # 字典格式
|
|
59
|
+
boundary='-----------------------------' + str(random.randint(int(1e28), int(1e29 - 1)))
|
|
60
|
+
)
|
|
61
|
+
return multipart
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
def check_headers_str_null(
|
|
65
|
+
cls,
|
|
66
|
+
headers: Dict) -> Dict:
|
|
67
|
+
"""
|
|
68
|
+
兼容用户未填写headers或者header值为int
|
|
69
|
+
@return:
|
|
70
|
+
"""
|
|
71
|
+
headers = ast.literal_eval(cache_regular(str(headers)))
|
|
72
|
+
if headers is None:
|
|
73
|
+
headers = {"headers": None}
|
|
74
|
+
else:
|
|
75
|
+
for key, value in headers.items():
|
|
76
|
+
if not isinstance(value, str):
|
|
77
|
+
headers[key] = str(value)
|
|
78
|
+
return headers
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def multipart_in_headers(
|
|
82
|
+
cls,
|
|
83
|
+
request_data: Dict,
|
|
84
|
+
header: Dict):
|
|
85
|
+
""" 判断处理header为 Content-Type: multipart/form-data"""
|
|
86
|
+
header = ast.literal_eval(cache_regular(str(header)))
|
|
87
|
+
request_data = ast.literal_eval(cache_regular(str(request_data)))
|
|
88
|
+
|
|
89
|
+
if header is None:
|
|
90
|
+
header = {"headers": None}
|
|
91
|
+
else:
|
|
92
|
+
# 将header中的int转换成str
|
|
93
|
+
for key, value in header.items():
|
|
94
|
+
if not isinstance(value, str):
|
|
95
|
+
header[key] = str(value)
|
|
96
|
+
if "multipart/form-data" in str(header.values()):
|
|
97
|
+
# 判断请求参数不为空, 并且参数是字典类型
|
|
98
|
+
if request_data and isinstance(request_data, dict):
|
|
99
|
+
# 当 Content-Type 为 "multipart/form-data"时,需要将数据类型转换成 str
|
|
100
|
+
for key, value in request_data.items():
|
|
101
|
+
if not isinstance(value, str):
|
|
102
|
+
request_data[key] = str(value)
|
|
103
|
+
|
|
104
|
+
request_data = MultipartEncoder(request_data)
|
|
105
|
+
header['Content-Type'] = request_data.content_type
|
|
106
|
+
|
|
107
|
+
return request_data, header
|
|
108
|
+
|
|
109
|
+
def file_prams_exit(self) -> Dict:
|
|
110
|
+
"""判断上传文件接口,文件参数是否存在"""
|
|
111
|
+
try:
|
|
112
|
+
params = self.__yaml_case.data['params']
|
|
113
|
+
except KeyError:
|
|
114
|
+
params = None
|
|
115
|
+
return params
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def text_encode(
|
|
119
|
+
cls,
|
|
120
|
+
text: Text) -> Text:
|
|
121
|
+
"""unicode 解码"""
|
|
122
|
+
return text.encode("utf-8").decode("utf-8")
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def response_elapsed_total_seconds(
|
|
126
|
+
cls,
|
|
127
|
+
res) -> float:
|
|
128
|
+
"""获取接口响应时长"""
|
|
129
|
+
try:
|
|
130
|
+
return round(res.elapsed.total_seconds() * 1000, 2)
|
|
131
|
+
except AttributeError:
|
|
132
|
+
return 0.00
|
|
133
|
+
|
|
134
|
+
def upload_file(
|
|
135
|
+
self) -> Tuple:
|
|
136
|
+
"""
|
|
137
|
+
判断处理上传文件
|
|
138
|
+
:return:
|
|
139
|
+
"""
|
|
140
|
+
# 处理上传多个文件的情况
|
|
141
|
+
_files = []
|
|
142
|
+
file_data = {}
|
|
143
|
+
# 兼容又要上传文件,又要上传其他类型参数
|
|
144
|
+
self.file_data_exit(file_data)
|
|
145
|
+
_data = self.__yaml_case.data
|
|
146
|
+
for key, value in ast.literal_eval(cache_regular(str(_data)))['file'].items():
|
|
147
|
+
file_path = ensure_path_sep("\\Files\\" + value)
|
|
148
|
+
file_data[key] = (value, open(file_path, 'rb'), 'application/octet-stream')
|
|
149
|
+
_files.append(file_data)
|
|
150
|
+
# allure中展示该附件
|
|
151
|
+
allure_attach(source=file_path, name=value, extension=value)
|
|
152
|
+
multipart = self.multipart_data(file_data)
|
|
153
|
+
# ast.literal_eval(cache_regular(str(_headers)))['Content-Type'] = multipart.content_type
|
|
154
|
+
self.__yaml_case.headers['Content-Type'] = multipart.content_type
|
|
155
|
+
params_data = ast.literal_eval(cache_regular(str(self.file_prams_exit())))
|
|
156
|
+
return multipart, params_data, self.__yaml_case
|
|
157
|
+
|
|
158
|
+
def request_type_for_json(
|
|
159
|
+
self,
|
|
160
|
+
headers: Dict,
|
|
161
|
+
method: Text,
|
|
162
|
+
**kwargs):
|
|
163
|
+
""" 判断请求类型为json格式 """
|
|
164
|
+
_headers = self.check_headers_str_null(headers)
|
|
165
|
+
_data = self.__yaml_case.data
|
|
166
|
+
_url = self.__yaml_case.url
|
|
167
|
+
res = requests.request(
|
|
168
|
+
method=method,
|
|
169
|
+
url=cache_regular(str(_url)),
|
|
170
|
+
json=ast.literal_eval(cache_regular(str(_data))),
|
|
171
|
+
data={},
|
|
172
|
+
headers=_headers,
|
|
173
|
+
verify=False,
|
|
174
|
+
params=None,
|
|
175
|
+
**kwargs
|
|
176
|
+
)
|
|
177
|
+
return res
|
|
178
|
+
|
|
179
|
+
def request_type_for_none(
|
|
180
|
+
self,
|
|
181
|
+
headers: Dict,
|
|
182
|
+
method: Text,
|
|
183
|
+
**kwargs) -> object:
|
|
184
|
+
"""判断 requestType 为 None"""
|
|
185
|
+
_headers = self.check_headers_str_null(headers)
|
|
186
|
+
_url = self.__yaml_case.url
|
|
187
|
+
res = requests.request(
|
|
188
|
+
method=method,
|
|
189
|
+
url=cache_regular(_url),
|
|
190
|
+
data=None,
|
|
191
|
+
headers=_headers,
|
|
192
|
+
verify=False,
|
|
193
|
+
params=None,
|
|
194
|
+
**kwargs
|
|
195
|
+
)
|
|
196
|
+
return res
|
|
197
|
+
|
|
198
|
+
def request_type_for_params(
|
|
199
|
+
self,
|
|
200
|
+
headers: Dict,
|
|
201
|
+
method: Text,
|
|
202
|
+
**kwargs):
|
|
203
|
+
|
|
204
|
+
"""处理 requestType 为 params """
|
|
205
|
+
_data = self.__yaml_case.data
|
|
206
|
+
url = self.__yaml_case.url
|
|
207
|
+
if _data is not None:
|
|
208
|
+
# url 拼接的方式传参
|
|
209
|
+
params_data = "?"
|
|
210
|
+
for key, value in _data.items():
|
|
211
|
+
if value is None or value == '':
|
|
212
|
+
params_data += (key + "&")
|
|
213
|
+
else:
|
|
214
|
+
params_data += (key + "=" + str(value) + "&")
|
|
215
|
+
url = self.__yaml_case.url + params_data[:-1]
|
|
216
|
+
_headers = self.check_headers_str_null(headers)
|
|
217
|
+
res = requests.request(
|
|
218
|
+
method=method,
|
|
219
|
+
url=cache_regular(url),
|
|
220
|
+
headers=_headers,
|
|
221
|
+
verify=False,
|
|
222
|
+
data={},
|
|
223
|
+
params=None,
|
|
224
|
+
**kwargs)
|
|
225
|
+
return res
|
|
226
|
+
|
|
227
|
+
def request_type_for_file(
|
|
228
|
+
self,
|
|
229
|
+
method: Text,
|
|
230
|
+
headers,
|
|
231
|
+
**kwargs):
|
|
232
|
+
"""处理 requestType 为 file 类型"""
|
|
233
|
+
multipart = self.upload_file()
|
|
234
|
+
yaml_data = multipart[2]
|
|
235
|
+
_headers = multipart[2].headers
|
|
236
|
+
_headers = self.check_headers_str_null(_headers)
|
|
237
|
+
res = requests.request(
|
|
238
|
+
method=method,
|
|
239
|
+
url=cache_regular(yaml_data.url),
|
|
240
|
+
data=multipart[0],
|
|
241
|
+
params=multipart[1],
|
|
242
|
+
headers=ast.literal_eval(cache_regular(str(_headers))),
|
|
243
|
+
verify=False,
|
|
244
|
+
**kwargs
|
|
245
|
+
)
|
|
246
|
+
return res
|
|
247
|
+
|
|
248
|
+
def request_type_for_data(
|
|
249
|
+
self,
|
|
250
|
+
headers: Dict,
|
|
251
|
+
method: Text,
|
|
252
|
+
**kwargs):
|
|
253
|
+
"""判断 requestType 为 data 类型"""
|
|
254
|
+
data = self.__yaml_case.data
|
|
255
|
+
_data, _headers = self.multipart_in_headers(
|
|
256
|
+
ast.literal_eval(cache_regular(str(data))),
|
|
257
|
+
headers
|
|
258
|
+
)
|
|
259
|
+
_url = self.__yaml_case.url
|
|
260
|
+
res = requests.request(
|
|
261
|
+
method=method,
|
|
262
|
+
url=cache_regular(_url),
|
|
263
|
+
data=_data,
|
|
264
|
+
headers=_headers,
|
|
265
|
+
verify=False,
|
|
266
|
+
**kwargs)
|
|
267
|
+
|
|
268
|
+
return res
|
|
269
|
+
|
|
270
|
+
@classmethod
|
|
271
|
+
def get_export_api_filename(cls, res):
|
|
272
|
+
""" 处理导出文件 """
|
|
273
|
+
content_disposition = res.headers.get('content-disposition')
|
|
274
|
+
filename_code = content_disposition.split("=")[-1] # 分隔字符串,提取文件名
|
|
275
|
+
filename = urllib.parse.unquote(filename_code) # url解码
|
|
276
|
+
return filename
|
|
277
|
+
|
|
278
|
+
def request_type_for_export(
|
|
279
|
+
self,
|
|
280
|
+
headers: Dict,
|
|
281
|
+
method: Text,
|
|
282
|
+
**kwargs):
|
|
283
|
+
"""判断 requestType 为 export 导出类型"""
|
|
284
|
+
_headers = self.check_headers_str_null(headers)
|
|
285
|
+
_data = self.__yaml_case.data
|
|
286
|
+
_url = self.__yaml_case.url
|
|
287
|
+
res = requests.request(
|
|
288
|
+
method=method,
|
|
289
|
+
url=cache_regular(_url),
|
|
290
|
+
json=ast.literal_eval(cache_regular(str(_data))),
|
|
291
|
+
headers=_headers,
|
|
292
|
+
verify=False,
|
|
293
|
+
stream=False,
|
|
294
|
+
data={},
|
|
295
|
+
**kwargs)
|
|
296
|
+
filepath = os.path.join(ensure_path_sep("\\Files\\"), self.get_export_api_filename(res)) # 拼接路径
|
|
297
|
+
if res.status_code == 200:
|
|
298
|
+
if res.text: # 判断文件内容是否为空
|
|
299
|
+
with open(filepath, 'wb') as file:
|
|
300
|
+
# iter_content循环读取信息写入,chunk_size设置文件大小
|
|
301
|
+
for chunk in res.iter_content(chunk_size=1):
|
|
302
|
+
file.write(chunk)
|
|
303
|
+
else:
|
|
304
|
+
print("文件为空")
|
|
305
|
+
|
|
306
|
+
return res
|
|
307
|
+
|
|
308
|
+
@classmethod
|
|
309
|
+
def _request_body_handler(cls, data: Dict, request_type: Text) -> Union[None, Dict]:
|
|
310
|
+
"""处理请求参数 """
|
|
311
|
+
if request_type.upper() == 'PARAMS':
|
|
312
|
+
return None
|
|
313
|
+
else:
|
|
314
|
+
return data
|
|
315
|
+
|
|
316
|
+
@classmethod
|
|
317
|
+
def _sql_data_handler(cls, sql_data, res):
|
|
318
|
+
"""处理 sql 参数 """
|
|
319
|
+
# 判断数据库开关,开启状态,则返回对应的数据
|
|
320
|
+
if config.mysql_db.switch and sql_data is not None:
|
|
321
|
+
sql_data = AssertExecution().assert_execution(
|
|
322
|
+
sql=sql_data,
|
|
323
|
+
resp=res.json()
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
else:
|
|
327
|
+
sql_data = {"sql": None}
|
|
328
|
+
return sql_data
|
|
329
|
+
|
|
330
|
+
def _check_params(
|
|
331
|
+
self,
|
|
332
|
+
res,
|
|
333
|
+
yaml_data: "TestCase",
|
|
334
|
+
) -> "ResponseData":
|
|
335
|
+
data = ast.literal_eval(cache_regular(str(yaml_data.data)))
|
|
336
|
+
_data = {
|
|
337
|
+
"url": res.url,
|
|
338
|
+
"is_run": yaml_data.is_run,
|
|
339
|
+
"detail": yaml_data.detail,
|
|
340
|
+
"response_data": res.text,
|
|
341
|
+
# 这个用于日志专用,判断如果是get请求,直接打印url
|
|
342
|
+
"request_body": self._request_body_handler(
|
|
343
|
+
data, yaml_data.requestType
|
|
344
|
+
),
|
|
345
|
+
"method": res.request.method,
|
|
346
|
+
"sql_data": self._sql_data_handler(sql_data=ast.literal_eval(cache_regular(str(yaml_data.sql))), res=res),
|
|
347
|
+
"yaml_data": yaml_data,
|
|
348
|
+
"headers": res.request.headers,
|
|
349
|
+
"cookie": res.cookies,
|
|
350
|
+
"assert_data": yaml_data.assert_data,
|
|
351
|
+
"res_time": self.response_elapsed_total_seconds(res),
|
|
352
|
+
"status_code": res.status_code,
|
|
353
|
+
"teardown": yaml_data.teardown,
|
|
354
|
+
"teardown_sql": yaml_data.teardown_sql,
|
|
355
|
+
"body": data
|
|
356
|
+
}
|
|
357
|
+
# 抽离出通用模块,判断 http_request 方法中的一些数据校验
|
|
358
|
+
return ResponseData(**_data)
|
|
359
|
+
|
|
360
|
+
@classmethod
|
|
361
|
+
def api_allure_step(
|
|
362
|
+
cls,
|
|
363
|
+
*,
|
|
364
|
+
url: Text,
|
|
365
|
+
headers: Text,
|
|
366
|
+
method: Text,
|
|
367
|
+
data: Text,
|
|
368
|
+
assert_data: Text,
|
|
369
|
+
res_time: Text,
|
|
370
|
+
res: Text
|
|
371
|
+
) -> None:
|
|
372
|
+
""" 在allure中记录请求数据 """
|
|
373
|
+
allure_step_no(f"请求URL: {url}")
|
|
374
|
+
allure_step_no(f"请求方式: {method}")
|
|
375
|
+
allure_step("请求头: ", headers)
|
|
376
|
+
allure_step("请求数据: ", data)
|
|
377
|
+
allure_step("预期数据: ", assert_data)
|
|
378
|
+
_res_time = res_time
|
|
379
|
+
allure_step_no(f"响应耗时(ms): {str(_res_time)}")
|
|
380
|
+
allure_step("响应结果: ", res)
|
|
381
|
+
|
|
382
|
+
@log_decorator(True)
|
|
383
|
+
@execution_duration(3000)
|
|
384
|
+
# @encryption("md5")
|
|
385
|
+
def http_request(
|
|
386
|
+
self,
|
|
387
|
+
dependent_switch=True,
|
|
388
|
+
**kwargs
|
|
389
|
+
):
|
|
390
|
+
"""
|
|
391
|
+
请求封装
|
|
392
|
+
:param dependent_switch:
|
|
393
|
+
:param kwargs:
|
|
394
|
+
:return:
|
|
395
|
+
"""
|
|
396
|
+
from utils.requests_tool.dependent_case import DependentCase
|
|
397
|
+
requests_type_mapping = {
|
|
398
|
+
RequestType.JSON.value: self.request_type_for_json,
|
|
399
|
+
RequestType.NONE.value: self.request_type_for_none,
|
|
400
|
+
RequestType.PARAMS.value: self.request_type_for_params,
|
|
401
|
+
RequestType.FILE.value: self.request_type_for_file,
|
|
402
|
+
RequestType.DATA.value: self.request_type_for_data,
|
|
403
|
+
RequestType.EXPORT.value: self.request_type_for_export
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
is_run = ast.literal_eval(cache_regular(str(self.__yaml_case.is_run)))
|
|
407
|
+
# 判断用例是否执行
|
|
408
|
+
if is_run is True or is_run is None:
|
|
409
|
+
# 处理多业务逻辑
|
|
410
|
+
if dependent_switch is True:
|
|
411
|
+
DependentCase(self.__yaml_case).get_dependent_data()
|
|
412
|
+
|
|
413
|
+
res = requests_type_mapping.get(self.__yaml_case.requestType)(
|
|
414
|
+
headers=self.__yaml_case.headers,
|
|
415
|
+
method=self.__yaml_case.method,
|
|
416
|
+
**kwargs
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
if self.__yaml_case.sleep is not None:
|
|
420
|
+
time.sleep(self.__yaml_case.sleep)
|
|
421
|
+
|
|
422
|
+
_res_data = self._check_params(
|
|
423
|
+
res=res,
|
|
424
|
+
yaml_data=self.__yaml_case)
|
|
425
|
+
|
|
426
|
+
self.api_allure_step(
|
|
427
|
+
url=_res_data.url,
|
|
428
|
+
headers=str(_res_data.headers),
|
|
429
|
+
method=_res_data.method,
|
|
430
|
+
data=str(_res_data.body),
|
|
431
|
+
assert_data=str(_res_data.assert_data),
|
|
432
|
+
res_time=str(_res_data.res_time),
|
|
433
|
+
res=_res_data.response_data
|
|
434
|
+
)
|
|
435
|
+
# 将当前请求数据存入缓存中
|
|
436
|
+
SetCurrentRequestCache(
|
|
437
|
+
current_request_set_cache=self.__yaml_case.current_request_set_cache,
|
|
438
|
+
request_data=self.__yaml_case.data,
|
|
439
|
+
response_data=res
|
|
440
|
+
).set_caches_main()
|
|
441
|
+
|
|
442
|
+
return _res_data
|
|
443
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
# @Time : 2022/6/2 11:30
|
|
5
|
+
# @Author : 余少琪
|
|
6
|
+
# @Email : 1603453211@qq.com
|
|
7
|
+
# @File : set_current_request_cache
|
|
8
|
+
# @describe:
|
|
9
|
+
"""
|
|
10
|
+
import json
|
|
11
|
+
from typing import Text
|
|
12
|
+
from jsonpath import jsonpath
|
|
13
|
+
from utils.other_tools.exceptions import ValueNotFoundError
|
|
14
|
+
from utils.cache_process.cache_control import CacheHandler
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SetCurrentRequestCache:
|
|
18
|
+
"""将用例中的请求或者响应内容存入缓存"""
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
current_request_set_cache,
|
|
23
|
+
request_data,
|
|
24
|
+
response_data
|
|
25
|
+
):
|
|
26
|
+
self.current_request_set_cache = current_request_set_cache
|
|
27
|
+
self.request_data = {"data": request_data}
|
|
28
|
+
self.response_data = response_data.text
|
|
29
|
+
|
|
30
|
+
def set_request_cache(
|
|
31
|
+
self,
|
|
32
|
+
jsonpath_value: Text,
|
|
33
|
+
cache_name: Text) -> None:
|
|
34
|
+
"""将接口的请求参数存入缓存"""
|
|
35
|
+
_request_data = jsonpath(
|
|
36
|
+
self.request_data,
|
|
37
|
+
jsonpath_value
|
|
38
|
+
)
|
|
39
|
+
if _request_data is not False:
|
|
40
|
+
CacheHandler.update_cache(cache_name=cache_name, value=_request_data[0])
|
|
41
|
+
# Cache(cache_name).set_caches(_request_data[0])
|
|
42
|
+
else:
|
|
43
|
+
raise ValueNotFoundError(
|
|
44
|
+
"缓存设置失败,程序中未检测到需要缓存的数据。"
|
|
45
|
+
f"请求参数: {self.request_data}"
|
|
46
|
+
f"提取的 jsonpath 内容: {jsonpath_value}"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def set_response_cache(
|
|
50
|
+
self,
|
|
51
|
+
jsonpath_value: Text,
|
|
52
|
+
cache_name
|
|
53
|
+
):
|
|
54
|
+
"""将响应结果存入缓存"""
|
|
55
|
+
_response_data = jsonpath(json.loads(self.response_data), jsonpath_value)
|
|
56
|
+
if _response_data is not False:
|
|
57
|
+
CacheHandler.update_cache(cache_name=cache_name, value=_response_data[0])
|
|
58
|
+
# Cache(cache_name).set_caches(_response_data[0])
|
|
59
|
+
else:
|
|
60
|
+
raise ValueNotFoundError("缓存设置失败,程序中未检测到需要缓存的数据。"
|
|
61
|
+
f"请求参数: {self.response_data}"
|
|
62
|
+
f"提取的 jsonpath 内容: {jsonpath_value}")
|
|
63
|
+
|
|
64
|
+
def set_caches_main(self):
|
|
65
|
+
"""设置缓存"""
|
|
66
|
+
if self.current_request_set_cache is not None:
|
|
67
|
+
for i in self.current_request_set_cache:
|
|
68
|
+
_jsonpath = i.jsonpath
|
|
69
|
+
_cache_name = i.name
|
|
70
|
+
if i.type == 'request':
|
|
71
|
+
self.set_request_cache(jsonpath_value=_jsonpath, cache_name=_cache_name)
|
|
72
|
+
elif i.type == 'response':
|
|
73
|
+
self.set_response_cache(jsonpath_value=_jsonpath, cache_name=_cache_name)
|