兼容处理请求参数为空时去提取请求参数导致日志打印错误问题
This commit is contained in:
parent
554261310c
commit
4b4eb0bfb6
|
@ -165,3 +165,35 @@ HTTPSConnectionPool(host='xxxx.com', port=443): Max retries exceeded with url: /
|
||||||
2023-07-14 23:00:30 | ERROR | 被提取对象非字典、非字符串、非列表,不执行jsonpath提取,被提取对象: None
|
2023-07-14 23:00:30 | ERROR | 被提取对象非字典、非字符串、非列表,不执行jsonpath提取,被提取对象: None
|
||||||
2023-07-14 23:00:33 | ERROR | 异常用例: safe_5_劳务基础配置_查询配置
|
2023-07-14 23:00:33 | ERROR | 异常用例: safe_5_劳务基础配置_查询配置
|
||||||
HTTPSConnectionPool(host='xxxx.com', port=443): Max retries exceeded with url: /test/api/getTvInfo?t=1689346830060&projectId=3333 (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000002D112A8BC70>: Failed to establish a new connection: [WinError 10061] 由于目标计算机积极拒绝,无法连接。'))
|
HTTPSConnectionPool(host='xxxx.com', port=443): Max retries exceeded with url: /test/api/getTvInfo?t=1689346830060&projectId=3333 (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000002D112A8BC70>: Failed to establish a new connection: [WinError 10061] 由于目标计算机积极拒绝,无法连接。'))
|
||||||
|
2023-07-14 23:31:50 | ERROR | key:<re.Match object; span=(152, 165), match='{{BSP_TOKEN}}'>,在关联参数表中查询不到,请检查关联参数字段提取及填写是否正常
|
||||||
|
|
||||||
|
2023-07-14 23:31:51 | ERROR | key:<re.Match object; span=(138, 151), match='{{BSP_TOKEN}}'>,在关联参数表中查询不到,请检查关联参数字段提取及填写是否正常
|
||||||
|
|
||||||
|
2023-07-14 23:31:51 | ERROR | 被提取对象非字典、非字符串、非列表,不执行jsonpath提取,被提取对象: None
|
||||||
|
2023-07-14 23:33:01 | ERROR | key:<re.Match object; span=(152, 165), match='{{BSP_TOKEN}}'>,在关联参数表中查询不到,请检查关联参数字段提取及填写是否正常
|
||||||
|
|
||||||
|
2023-07-14 23:33:13 | ERROR | key:<re.Match object; span=(138, 151), match='{{BSP_TOKEN}}'>,在关联参数表中查询不到,请检查关联参数字段提取及填写是否正常
|
||||||
|
|
||||||
|
2023-07-14 23:33:13 | ERROR | 被提取对象非字典、非字符串、非列表,不执行jsonpath提取,被提取对象: None
|
||||||
|
2023-07-14 23:38:02 | ERROR | key:<re.Match object; span=(152, 165), match='{{BSP_TOKEN}}'>,在关联参数表中查询不到,请检查关联参数字段提取及填写是否正常
|
||||||
|
|
||||||
|
2023-07-14 23:38:15 | ERROR | key:<re.Match object; span=(138, 151), match='{{BSP_TOKEN}}'>,在关联参数表中查询不到,请检查关联参数字段提取及填写是否正常
|
||||||
|
|
||||||
|
2023-07-14 23:38:15 | ERROR | 被提取对象非字典、非字符串、非列表,不执行jsonpath提取,被提取对象: None
|
||||||
|
2023-07-14 23:45:41 | ERROR | key:<re.Match object; span=(152, 165), match='{{BSP_TOKEN}}'>,在关联参数表中查询不到,请检查关联参数字段提取及填写是否正常
|
||||||
|
|
||||||
|
2023-07-14 23:45:51 | ERROR | key:<re.Match object; span=(138, 151), match='{{BSP_TOKEN}}'>,在关联参数表中查询不到,请检查关联参数字段提取及填写是否正常
|
||||||
|
|
||||||
|
2023-07-14 23:45:51 | ERROR | 被提取对象非字典、非字符串、非列表,不执行jsonpath提取,被提取对象: None
|
||||||
|
2023-07-14 23:54:12 | ERROR | 被提取对象非字典、非字符串、非列表,不执行jsonpath提取,被提取对象: None
|
||||||
|
2023-07-14 23:54:12 | ERROR | 提取失败:提取表达式:data.projectId,没有提取到对应的值
|
||||||
|
2023-07-14 23:54:12 | ERROR | 异常用例: **safe_5_劳务基础配置_查询配置**
|
||||||
|
'FAIL' unexpectedly found in ('FAIL', [{'检查项': 'data.projectId', '期望值': '103654', '实际值': [], '断言方法': 'contained_by:实际值被包含在期望值中'}]) : FAIL 存在结果元组中
|
||||||
|
2023-07-14 23:56:41 | ERROR | 被提取对象非字典、非字符串、非列表,不执行jsonpath提取,被提取对象: None
|
||||||
|
2023-07-14 23:56:41 | ERROR | 提取失败:提取表达式:data.projectId,没有提取到对应的值
|
||||||
|
2023-07-14 23:56:41 | ERROR | 异常用例: **safe_5_劳务基础配置_查询配置**
|
||||||
|
'FAIL' unexpectedly found in ('FAIL', [{'检查项': 'data.projectId', '期望值': '103654', '实际值': [], '断言方法': 'contained_by:实际值被包含在期望值中'}]) : FAIL 存在结果元组中
|
||||||
|
2023-07-14 23:57:22 | ERROR | 被提取对象非字典、非字符串、非列表,不执行jsonpath提取,被提取对象: None
|
||||||
|
2023-07-14 23:57:22 | ERROR | 提取失败:提取表达式:data.projectId,没有提取到对应的值
|
||||||
|
2023-07-14 23:57:23 | ERROR | 异常用例: **safe_5_劳务基础配置_查询配置**
|
||||||
|
'FAIL' unexpectedly found in ('FAIL', [{'检查项': 'data.projectId', '期望值': '103654', '实际值': [], '断言方法': 'contained_by:实际值被包含在期望值中'}]) : FAIL 存在结果元组中
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
2023-07-15 00:01:21 | ERROR | 被提取对象非字典、非字符串、非列表,不执行jsonpath提取,被提取对象: None
|
||||||
|
2023-07-15 00:01:21 | ERROR | 提取失败:提取表达式:data.projectId,没有提取到对应的值
|
||||||
|
2023-07-15 00:01:21 | ERROR | 异常用例: **safe_5_劳务基础配置_查询配置**
|
||||||
|
'FAIL' unexpectedly found in ('FAIL', [{'检查项': 'data.projectId', '期望值': '103654', '实际值': [], '断言方法': 'contained_by:实际值被包含在期望值中'}]) : FAIL 存在结果元组中
|
||||||
|
2023-07-15 00:07:51 | ERROR | | called clear_date | error: 快看,异常了,别唧唧哇哇,快排查!!: [Errno 13] Permission denied: 'E:\\apitest\\cases\\cases\\test_api.xlsx'
|
||||||
|
2023-07-15 00:07:52 | ERROR | | called write_back | error: 快看,异常了,别唧唧哇哇,快排查!!: [Errno 13] Permission denied: 'E:\\apitest\\cases\\cases\\test_api.xlsx'
|
||||||
|
2023-07-15 00:11:01 | ERROR | 提取失败:提取表达式:data.projectId,没有提取到对应的值
|
||||||
|
2023-07-15 00:11:01 | ERROR | 异常用例: **safe_5_劳务基础配置_查询配置**
|
||||||
|
'FAIL' unexpectedly found in ('FAIL', [{'检查项': 'data.projectId', '期望值': '103654', '实际值': [], '断言方法': 'contained_by:实际值被包含在期望值中'}]) : FAIL 存在结果元组中
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -33,17 +33,17 @@ class Action(Extractor, LoadScript, Validator):
|
||||||
compiled = compile(ast_obj, '<string>', 'exec')
|
compiled = compile(ast_obj, '<string>', 'exec')
|
||||||
exec(compiled, {"pm": self})
|
exec(compiled, {"pm": self})
|
||||||
except SyntaxError as e:
|
except SyntaxError as e:
|
||||||
error_message = f'Syntax error in dynamic code: {e}'
|
error_message = f'动态代码语法异常: {e}'
|
||||||
self._handle_error(error_message)
|
self._handle_error(error_message)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_message = f"Error executing dynamic code: {e}"
|
error_message = f"动态代码执行异常: {e}"
|
||||||
self._handle_error(error_message)
|
self._handle_error(error_message)
|
||||||
finally:
|
finally:
|
||||||
return self.__variables
|
return self.__variables
|
||||||
return item
|
return item
|
||||||
|
|
||||||
def _handle_error(self, error_message):
|
def _handle_error(self, error_message):
|
||||||
print(f'Error occurred: {error_message}')
|
print(f'发现异常: {error_message}')
|
||||||
|
|
||||||
def set_variables(self, item):
|
def set_variables(self, item):
|
||||||
self.__variables = item
|
self.__variables = item
|
||||||
|
@ -59,5 +59,11 @@ class Action(Extractor, LoadScript, Validator):
|
||||||
# 请求头及body加密或者加签
|
# 请求头及body加密或者加签
|
||||||
headers, request_data = self.encrypt.encrypts(headers_crypto, headers, request_crypto, request_data)
|
headers, request_data = self.encrypt.encrypts(headers_crypto, headers, request_crypto, request_data)
|
||||||
# 提取请求参数信息
|
# 提取请求参数信息
|
||||||
self.substitute_data(request_data, jp_dict=extract_request_data)
|
if extract_request_data is not None and request_data is not None:
|
||||||
|
self.substitute_data(request_data, jp_dict=extract_request_data)
|
||||||
return headers, request_data
|
return headers, request_data
|
||||||
|
|
||||||
|
def send_request(self, host, url, method, teardown_script, **kwargs):
|
||||||
|
response = self.http_client(host, url, method, **kwargs)
|
||||||
|
self.execute_dynamic_code(response, teardown_script)
|
||||||
|
return response
|
||||||
|
|
|
@ -12,11 +12,10 @@ sys.path.append("./common")
|
||||||
|
|
||||||
from common.validation.load_modules_from_folder import LoadModulesFromFolder
|
from common.validation.load_modules_from_folder import LoadModulesFromFolder
|
||||||
from common.file_handling.file_utils import FileUtils
|
from common.file_handling.file_utils import FileUtils
|
||||||
from common.utils.decorators import request_decorator
|
from common.utils.decorators import request_retry_on_exception
|
||||||
|
|
||||||
|
|
||||||
class Pyt(LoadModulesFromFolder):
|
class Pyt(LoadModulesFromFolder):
|
||||||
# 类属性,保存一个会话对象,防止每次都创建一个新的会话,节省资源
|
|
||||||
session = requests.Session()
|
session = requests.Session()
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -24,7 +23,7 @@ class Pyt(LoadModulesFromFolder):
|
||||||
self.request = None
|
self.request = None
|
||||||
self.response = None
|
self.response = None
|
||||||
|
|
||||||
@request_decorator
|
@request_retry_on_exception()
|
||||||
def http_client(self, host, url, method, **kwargs):
|
def http_client(self, host, url, method, **kwargs):
|
||||||
"""
|
"""
|
||||||
发送 http 请求
|
发送 http 请求
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
@time: 2023/3/21 17:41
|
@time: 2023/3/21 17:41
|
||||||
@desc:
|
@desc:
|
||||||
"""
|
"""
|
||||||
|
import time
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,21 +28,30 @@ def singleton(cls):
|
||||||
return get_instance
|
return get_instance
|
||||||
|
|
||||||
|
|
||||||
def request_decorator(func):
|
def request_retry_on_exception(retries=2, delay=1.5):
|
||||||
@wraps(func)
|
def request_decorator(func):
|
||||||
def wrapper(*args, **kwargs):
|
e = None
|
||||||
try:
|
|
||||||
print(f"发送请求的参数: {kwargs}")
|
|
||||||
response = func(*args, **kwargs)
|
|
||||||
print(f"请求地址 --> {response.request.url}")
|
|
||||||
print(f"请求头 --> {response.request.headers}")
|
|
||||||
print(f"请求 body --> {response.request.body}")
|
|
||||||
print(f"接口状态--> {response.status_code}")
|
|
||||||
print(f"接口耗时--> {response.elapsed}")
|
|
||||||
print(f"接口响应--> {response.text}")
|
|
||||||
return response
|
|
||||||
except Exception as e:
|
|
||||||
print(f"接口异常--> {e}")
|
|
||||||
raise e
|
|
||||||
|
|
||||||
return wrapper
|
@wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
nonlocal e
|
||||||
|
for i in range(retries):
|
||||||
|
try:
|
||||||
|
print(f"第{i}次发送请求的参数: {kwargs}")
|
||||||
|
response = func(*args, **kwargs)
|
||||||
|
print(f"请求地址 --> {response.request.url}")
|
||||||
|
print(f"请求头 --> {response.request.headers}")
|
||||||
|
print(f"请求 body --> {response.request.body}")
|
||||||
|
print(f"接口状态--> {response.status_code}")
|
||||||
|
print(f"接口耗时--> {response.elapsed}")
|
||||||
|
print(f"接口响应--> {response.text}")
|
||||||
|
except Exception as error:
|
||||||
|
e = error
|
||||||
|
time.sleep(delay)
|
||||||
|
else:
|
||||||
|
return response
|
||||||
|
raise Exception(f"请求重试**{retries}**次失败,请检查!!{e}")
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
return request_decorator
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -62,16 +62,15 @@ class TestProjectApi(unittest.TestCase):
|
||||||
headers, request_data = self.action.analysis_request(request_data, h_crypto, headers, r_crypto, ex_request_data)
|
headers, request_data = self.action.analysis_request(request_data, h_crypto, headers, r_crypto, ex_request_data)
|
||||||
result_tuple = None
|
result_tuple = None
|
||||||
result = "PASS"
|
result = "PASS"
|
||||||
response = None
|
|
||||||
|
# 执行请求操作
|
||||||
|
kwargs = {request_data_type: request_data, 'headers': headers, "params": query_str}
|
||||||
|
# response = self.action.http_client(host, url, method, **kwargs)
|
||||||
|
# 执行后置代码片段
|
||||||
|
# self.action.execute_dynamic_code(response, teardown_script)
|
||||||
|
response = self.action.send_request(host, url, method, teardown_script, **kwargs)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 执行请求操作
|
|
||||||
kwargs = {request_data_type: request_data, 'headers': headers, "params": query_str}
|
|
||||||
response = self.action.http_client(host, url, method, **kwargs)
|
|
||||||
|
|
||||||
# 执行后置代码片段
|
|
||||||
self.action.execute_dynamic_code(response, teardown_script)
|
|
||||||
|
|
||||||
# 执行断言 返回结果元组
|
# 执行断言 返回结果元组
|
||||||
result_tuple = self.action.run_validate(expected, response.json())
|
result_tuple = self.action.run_validate(expected, response.json())
|
||||||
self.assertNotIn("FAIL", result_tuple, "FAIL 存在结果元组中")
|
self.assertNotIn("FAIL", result_tuple, "FAIL 存在结果元组中")
|
||||||
|
|
Loading…
Reference in New Issue