diff --git a/.idea/api_project.iml b/.idea/api_project.iml
index 8bbb12f..d79ef17 100644
--- a/.idea/api_project.iml
+++ b/.idea/api_project.iml
@@ -5,7 +5,7 @@
-
+
diff --git a/.idea/dataSources.local.xml b/.idea/dataSources.local.xml
index 37e6fc8..3b44b4e 100644
--- a/.idea/dataSources.local.xml
+++ b/.idea/dataSources.local.xml
@@ -1,6 +1,6 @@
-
+
#@
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 8978351..93e7776 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/cases/cases/test_api.xlsx b/cases/cases/test_api.xlsx
index f25e7f7..d2adeb1 100644
Binary files a/cases/cases/test_api.xlsx and b/cases/cases/test_api.xlsx differ
diff --git a/common/action.py b/common/action.py
index 55e0652..75a7acb 100644
--- a/common/action.py
+++ b/common/action.py
@@ -18,46 +18,46 @@ from common.validation.validator import Validator
@singleton
class Action(Extractor, LoadScript, Validator):
- def __init__(self, initialize_data=None, bif_functions=None):
- super().__init__()
- self.encrypt = EncryptData()
- self.__variables = {}
- self.set_environments(initialize_data)
- self.set_bif_fun(bif_functions)
-
- def execute_dynamic_code(self, item, code):
- self.set_variables(item)
- if code is not None:
- try:
- ast_obj = ast.parse(code, mode='exec')
- compiled = compile(ast_obj, '', 'exec')
- exec(compiled, {"pm": self})
- except SyntaxError as e:
- error_message = f'Syntax error in dynamic code: {e}'
- self._handle_error(error_message)
- except Exception as e:
- error_message = f"Error executing dynamic code: {e}"
- self._handle_error(error_message)
- finally:
- return self.__variables
- return item
-
- def _handle_error(self, error_message):
- print(f'Error occurred: {error_message}')
-
- def set_variables(self, item):
- self.__variables = item
-
- def update_variables(self, key, value):
- self.__variables[f"{{{{{key}}}}}"] = value
-
- def get_variables(self, key=None):
- """获取依赖表 或 依赖表中key对应的值"""
- return self.__variables if not key else self.__variables.get(key)
-
- def analysis_request(self, request_data, headers_crypto, headers, request_crypto, extract_request_data):
- # 请求头及body加密或者加签
- headers, request_data = self.encrypt.encrypts(headers_crypto, headers, request_crypto, request_data)
- # 提取请求参数信息
- self.substitute_data(request_data, jp_dict=extract_request_data)
- return headers, request_data
+ def __init__(self, initialize_data=None, bif_functions=None):
+ super().__init__()
+ self.encrypt = EncryptData()
+ self.__variables = {}
+ self.set_environments(initialize_data)
+ self.set_bif_fun(bif_functions)
+
+ def execute_dynamic_code(self, item, code):
+ self.set_variables(item)
+ if code is not None:
+ try:
+ ast_obj = ast.parse(code, mode='exec')
+ compiled = compile(ast_obj, '', 'exec')
+ exec(compiled, {"pm": self})
+ except SyntaxError as e:
+ error_message = f'Syntax error in dynamic code: {e}'
+ self._handle_error(error_message)
+ except Exception as e:
+ error_message = f"Error executing dynamic code: {e}"
+ self._handle_error(error_message)
+ finally:
+ return self.__variables
+ return item
+
+ def _handle_error(self, error_message):
+ print(f'Error occurred: {error_message}')
+
+ def set_variables(self, item):
+ self.__variables = item
+
+ def update_variables(self, key, value):
+ self.__variables[f"{{{{{key}}}}}"] = value
+
+ def get_variables(self, key=None):
+ """获取依赖表 或 依赖表中key对应的值"""
+ return self.__variables if not key else self.__variables.get(key)
+
+ def analysis_request(self, request_data, headers_crypto, headers, request_crypto, extract_request_data):
+ # 请求头及body加密或者加签
+ headers, request_data = self.encrypt.encrypts(headers_crypto, headers, request_crypto, request_data)
+ # 提取请求参数信息
+ self.substitute_data(request_data, jp_dict=extract_request_data)
+ return headers, request_data
diff --git a/common/data_extraction/data_extractor.py b/common/data_extraction/data_extractor.py
index e5851ab..b795641 100644
--- a/common/data_extraction/data_extractor.py
+++ b/common/data_extraction/data_extractor.py
@@ -124,7 +124,6 @@ class DataExtractor(Environments):
Returns: 字符串或者list
"""
-
json_path_dict = json_path_dict if isinstance(json_path_dict, dict) else json.loads(json_path_dict)
for key, expression in json_path_dict.items():
try:
diff --git a/common/data_extraction/dependent_parameter.py b/common/data_extraction/dependent_parameter.py
index b0ce61c..b579ec3 100644
--- a/common/data_extraction/dependent_parameter.py
+++ b/common/data_extraction/dependent_parameter.py
@@ -46,7 +46,6 @@ class DependentParameter(DataExtractor):
# 函数替换
key = self.pattern_fun.search(jst).group()
if key in self.get_environments().keys():
-
# 如果参数名称存在于关联参数表中,则调用相应的函数获取返回值,并替换字符串中的参数
value_ = self.get_environments(key)()
jst = jst.replace(key, str(value_))
diff --git a/common/http_client/http_client.py b/common/http_client/http_client.py
index 727d7e4..15d913e 100644
--- a/common/http_client/http_client.py
+++ b/common/http_client/http_client.py
@@ -10,7 +10,6 @@ import urllib3
sys.path.append("../")
sys.path.append("./common")
-from common.http_client import logger
from common.validation.load_modules_from_folder import LoadModulesFromFolder
from common.file_handling.file_utils import FileUtils
from common.utils.decorators import request_decorator
diff --git a/test_script/test_api.py b/test_script/test_api.py
index 8dba591..0a192d4 100644
--- a/test_script/test_api.py
+++ b/test_script/test_api.py
@@ -25,173 +25,174 @@ host = init_data.get('host', "") + init_data.get("path", "")
@ddt
class TestProjectApi(unittest.TestCase):
- maxDiff = None
- action = Action(initialize_data, bif_functions)
-
- @classmethod
- def setUpClass(cls) -> None:
- pass
-
- def setUp(self) -> None:
- self.action.set_bif_fun(dynamic_scaling_methods)
-
- @data(*test_case)
- def test_api(self, item):
-
- sheet, iid, condition, st, name, desc, h_crypto, r_crypto, method = self.__base_info(item)
- regex, keys, deps, jp_dict, extract_request_data = self.__extractor_info(item)
- setup_script, teardown_script = self.script(item)
-
- if self.__is_run(condition):
- return
-
- self.__pause_execution(st)
-
- # 首执行 sql
- self.__exc_sql(item, method)
-
- # 执行动态代码
- item = self.action.execute_dynamic_code(item, setup_script)
-
- # prepost_script = f"prepost_script_{sheet}_{iid}.py"
- # item = self.action.load_and_execute_script(Config.SCRIPTS_DIR, prepost_script, "setup", item)
-
- # 修正参数
- item = self.action.replace_dependent_parameter(item)
- url, query_str, request_data, headers, expected, request_data_type = self.__request_info(item)
-
- # 分析请求参数信息
- headers, request_data = self.action.analysis_request(request_data, h_crypto, headers, r_crypto,extract_request_data)
- result_tuple = None
- result = "PASS"
- response = None
-
- 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())
- self.assertNotIn("FAIL", result_tuple, "FAIL 存在结果元组中")
- try:
- # 提取响应
- self.action.substitute_data(response.json(), regex=regex, keys=keys, deps=deps, jp_dict=jp_dict)
-
- except Exception as err:
- logger.error(f"提取响应失败:{sheet}_{iid}_{name}_{desc}"
- f"\nregex={regex};"
- f" \nkeys={keys};"
- f"\ndeps={deps};"
- f"\njp_dict={jp_dict}"
- f"\n{err}")
- except Exception as e:
- result = "FAIL"
- logger.error(f'异常用例: {sheet}_{iid}_{name}_{desc}\n{e}')
- raise e
- finally:
- response = response.text if response is not None else str(response)
- # 响应结果及测试结果回写 excel
- excel.write_back(sheet_name=sheet, i=iid, response=response, test_result=result,
- assert_log=str(result_tuple))
-
- @classmethod
- def tearDownClass(cls) -> None:
- excel.close_excel()
- logger.info(f"所有用例执行完毕")
-
- @staticmethod
- def __base_info(item):
- """
- 获取基础信息
- """
- sheet = item.pop("sheet")
- item_id = item.pop("Id")
- condition = item.pop("Run")
- sleep_time = item.pop("Time")
- name = item.pop("Name")
- desc = item.pop("Description")
- headers_crypto = item.pop("Headers Crypto")
- request_data_crypto = item.pop("Request Data Crypto")
- method = item.pop("Method")
- return sheet, item_id, condition, sleep_time, name, desc, headers_crypto, request_data_crypto, method
-
- @staticmethod
- def __sql_info(item):
- sql = item.pop("SQL")
- sql_params_dict = item.pop("Sql Params Dict")
- return sql, sql_params_dict
-
- @staticmethod
- def __extractor_info(item):
- """
- 获取提取参数的基本字段信息
- Args:
- item:
-
- Returns:
-
- """
- regex = item.pop("Regex")
- keys = item.pop("Regex Params List")
- deps = item.pop("Retrieve Value")
- jp_dict = item.pop("Jsonpath")
- extract_request_data = item.pop("Extract Request Data")
- return regex, keys, deps, jp_dict, extract_request_data
-
- @staticmethod
- def __request_info(item):
- """
- 请求数据
- """
- url = item.pop("Url")
- query_str = item.pop("Query Str")
- request_data = item.pop("Request Data")
- headers = item.pop("Headers")
- expected = item.pop("Expected")
- request_data_type = item.pop("Request Data Type") if item.get("Request Data Type") else 'params'
-
- return url, query_str, request_data, headers, expected, request_data_type
-
- @staticmethod
- def script(item):
- setup_script = item.pop("Setup Script")
- teardown_script = item.pop("Teardown Script")
- return setup_script, teardown_script
-
- @staticmethod
- def __is_run(condition):
- is_run = condition
- if not is_run or is_run.upper() != "YES":
- return True
-
- @staticmethod
- def __pause_execution(sleep_time):
- if sleep_time:
- try:
- time.sleep(sleep_time)
- except Exception as e:
- logger.error("暂时时间必须是数字")
- raise e
-
- def __exc_sql(self, item, method):
- sql, sql_params_dict = self.__sql_info(item)
- sql = self.action.replace_dependent_parameter(sql)
- if sql:
- try:
- execute_sql_results = mysql.do_mysql(sql)
- if execute_sql_results and sql_params_dict:
- self.action.extract_request_data(execute_sql_results, jp_dict=sql_params_dict)
- if method == "SQL" and mysql:
- return None
- except Exception as e:
- logger.error(f'执行 sql 失败:{sql},异常信息:{e}')
- raise e
- return sql
+ maxDiff = None
+ action = Action(initialize_data, bif_functions)
+
+ @classmethod
+ def setUpClass(cls) -> None:
+ pass
+
+ def setUp(self) -> None:
+ self.action.set_bif_fun(dynamic_scaling_methods)
+
+ @data(*test_case)
+ def test_api(self, item):
+
+ sheet, iid, condition, st, name, desc, h_crypto, r_crypto, method = self.__base_info(item)
+ regex, keys, deps, jp_dict, extract_request_data = self.__extractor_info(item)
+ setup_script, teardown_script = self.script(item)
+
+ if self.__is_run(condition):
+ return
+
+ self.__pause_execution(st)
+
+ # 首执行 sql
+ self.__exc_sql(item, method)
+
+ # 执行动态代码
+ item = self.action.execute_dynamic_code(item, setup_script)
+
+ # prepost_script = f"prepost_script_{sheet}_{iid}.py"
+ # item = self.action.load_and_execute_script(Config.SCRIPTS_DIR, prepost_script, "setup", item)
+
+ # 修正参数
+ item = self.action.replace_dependent_parameter(item)
+ url, query_str, request_data, headers, expected, request_data_type = self.__request_info(item)
+
+ # 分析请求参数信息
+ headers, request_data = self.action.analysis_request(request_data, h_crypto, headers, r_crypto,
+ extract_request_data)
+ result_tuple = None
+ result = "PASS"
+ response = None
+
+ 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())
+ self.assertNotIn("FAIL", result_tuple, "FAIL 存在结果元组中")
+ try:
+ # 提取响应
+ self.action.substitute_data(response.json(), regex=regex, keys=keys, deps=deps, jp_dict=jp_dict)
+
+ except Exception as err:
+ logger.error(f"提取响应失败:{sheet}_{iid}_{name}_{desc}"
+ f"\nregex={regex};"
+ f" \nkeys={keys};"
+ f"\ndeps={deps};"
+ f"\njp_dict={jp_dict}"
+ f"\n{err}")
+ except Exception as e:
+ result = "FAIL"
+ logger.error(f'异常用例: {sheet}_{iid}_{name}_{desc}\n{e}')
+ raise e
+ finally:
+ response = response.text if response is not None else str(response)
+ # 响应结果及测试结果回写 excel
+ excel.write_back(sheet_name=sheet, i=iid, response=response, test_result=result,
+ assert_log=str(result_tuple))
+
+ @classmethod
+ def tearDownClass(cls) -> None:
+ excel.close_excel()
+ logger.info(f"所有用例执行完毕")
+
+ @staticmethod
+ def __base_info(item):
+ """
+ 获取基础信息
+ """
+ sheet = item.pop("sheet")
+ item_id = item.pop("Id")
+ condition = item.pop("Run")
+ sleep_time = item.pop("Time")
+ name = item.pop("Name")
+ desc = item.pop("Description")
+ headers_crypto = item.pop("Headers Crypto")
+ request_data_crypto = item.pop("Request Data Crypto")
+ method = item.pop("Method")
+ return sheet, item_id, condition, sleep_time, name, desc, headers_crypto, request_data_crypto, method
+
+ @staticmethod
+ def __sql_info(item):
+ sql = item.pop("SQL")
+ sql_params_dict = item.pop("Sql Params Dict")
+ return sql, sql_params_dict
+
+ @staticmethod
+ def __extractor_info(item):
+ """
+ 获取提取参数的基本字段信息
+ Args:
+ item:
+
+ Returns:
+
+ """
+ regex = item.pop("Regex")
+ keys = item.pop("Regex Params List")
+ deps = item.pop("Retrieve Value")
+ jp_dict = item.pop("Jsonpath")
+ extract_request_data = item.pop("Extract Request Data")
+ return regex, keys, deps, jp_dict, extract_request_data
+
+ @staticmethod
+ def __request_info(item):
+ """
+ 请求数据
+ """
+ url = item.pop("Url")
+ query_str = item.pop("Query Str")
+ request_data = item.pop("Request Data")
+ headers = item.pop("Headers")
+ expected = item.pop("Expected")
+ request_data_type = item.pop("Request Data Type") if item.get("Request Data Type") else 'params'
+
+ return url, query_str, request_data, headers, expected, request_data_type
+
+ @staticmethod
+ def script(item):
+ setup_script = item.pop("Setup Script")
+ teardown_script = item.pop("Teardown Script")
+ return setup_script, teardown_script
+
+ @staticmethod
+ def __is_run(condition):
+ is_run = condition
+ if not is_run or is_run.upper() != "YES":
+ return True
+
+ @staticmethod
+ def __pause_execution(sleep_time):
+ if sleep_time:
+ try:
+ time.sleep(sleep_time)
+ except Exception as e:
+ logger.error("暂时时间必须是数字")
+ raise e
+
+ def __exc_sql(self, item, method):
+ sql, sql_params_dict = self.__sql_info(item)
+ sql = self.action.replace_dependent_parameter(sql)
+ if sql:
+ try:
+ execute_sql_results = mysql.do_mysql(sql)
+ if execute_sql_results and sql_params_dict:
+ self.action.extract_request_data(execute_sql_results, jp_dict=sql_params_dict)
+ if method == "SQL" and mysql:
+ return None
+ except Exception as e:
+ logger.error(f'执行 sql 失败:{sql},异常信息:{e}')
+ raise e
+ return sql
if __name__ == '__main__':
- unittest.main()
+ unittest.main()