diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml
new file mode 100644
index 0000000..02b915b
--- /dev/null
+++ b/.idea/git_toolbox_prj.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 872860a..ed76a98 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,12 +4,15 @@
-
+
+
-
-
-
-
+
+
+
+
+
+
@@ -66,34 +69,13 @@
}
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -116,6 +98,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -138,28 +164,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -177,11 +181,11 @@
+
+
-
-
@@ -211,7 +215,8 @@
-
+
+
@@ -285,7 +290,15 @@
1690854560996
-
+
+
+ 1690858708660
+
+
+
+ 1690858708660
+
+
@@ -298,7 +311,8 @@
-
+
+
@@ -318,6 +332,8 @@
+
+
diff --git a/common/crypto/encrypt_data.py b/common/crypto/encrypt_data.py
index f65bef3..5edb59d 100644
--- a/common/crypto/encrypt_data.py
+++ b/common/crypto/encrypt_data.py
@@ -10,7 +10,7 @@
from common.crypto import logger
from common.crypto.encryption_rsa import Rsa
# from common.crypto.encryption_aes import DoAES
-from extensions import sign
+from encryption_rules import rules
@logger.log_decorator()
@@ -21,8 +21,8 @@ class EncryptData:
def encrypts(self, headers_crypto, headers, request_data_crypto, request_data):
encryption_methods = {
- "MD5": sign.md5_sign,
- "sha1": sign.sha1_sign,
+ "MD5": rules.md5_sign,
+ "sha1": rules.sha1_sign,
"rsa": lambda data: Rsa(data).rsa_encrypt()
}
diff --git a/common/utils/action.py b/common/utils/action.py
index 38528e2..30c33ad 100644
--- a/common/utils/action.py
+++ b/common/utils/action.py
@@ -10,6 +10,7 @@
import ast
import time
+from common import bif_functions
from common.crypto.encrypt_data import EncryptData
from common.database.mysql_client import MysqlClient
from common.log_utils.mylogger import MyLogger
@@ -22,7 +23,7 @@ from common.validation.validator import Validator
@singleton
class Action(Extractor, LoadScript, Validator, MysqlClient):
- def __init__(self, initialize_data=None, bif_functions=None, db_config=None):
+ def __init__(self, initialize_data=None, db_config=None):
super().__init__()
MysqlClient.__init__(self, db_config)
self.encrypt = EncryptData()
@@ -30,7 +31,7 @@ class Action(Extractor, LoadScript, Validator, MysqlClient):
self.set_environments(initialize_data)
self.set_bif_fun(bif_functions)
self.logger = MyLogger()
-
+
def execute_dynamic_code(self, item, code):
self.variables = item
if code is not None:
@@ -42,20 +43,20 @@ class Action(Extractor, LoadScript, Validator, MysqlClient):
ExecuteDynamiCodeError(code, e)
except ExecuteDynamiCodeError as e:
ExecuteDynamiCodeError(code, e)
-
+
return self.variables
-
+
@property
def variables(self, key=None):
return self.__variables if not key else self.__variables.get(key)
-
+
@variables.setter
def variables(self, item):
self.__variables = item
-
+
# def update_variables(self, key, value):
# self.__variables[f"{{{{{key}}}}}"] = value
-
+
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)
@@ -63,12 +64,12 @@ class Action(Extractor, LoadScript, Validator, MysqlClient):
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
-
+
def send_request(self, host, url, method, teardown_script, **kwargs):
self.http_client(host, url, method, **kwargs)
self.update_environments("responseTime", self.response.elapsed.total_seconds() * 1000) # 存响应时间
self.execute_dynamic_code(self.response, teardown_script)
-
+
@staticmethod
def base_info(item):
"""
@@ -85,13 +86,13 @@ class Action(Extractor, LoadScript, Validator, MysqlClient):
method = item.pop("Method")
expected = item.pop("Expected")
return sheet, item_id, condition, sleep_time, name, desc, headers_crypto, request_data_crypto, method, expected
-
+
@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):
"""
@@ -108,7 +109,7 @@ class Action(Extractor, LoadScript, Validator, MysqlClient):
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):
"""
@@ -119,28 +120,28 @@ class Action(Extractor, LoadScript, Validator, MysqlClient):
request_data = item.pop("Request Data")
headers = item.pop("Headers")
request_data_type = item.pop("Request Data Type") if item.get("Request Data Type") else 'params'
-
+
return url, query_str, request_data, headers, 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
-
+
def pause_execution(self, sleep_time):
if sleep_time:
try:
time.sleep(sleep_time)
except MyBaseException as e:
raise MyBaseException(f"暂停时间必须是数字!")
-
+
def exc_sql(self, item):
sql, sql_params_dict = self.sql_info(item)
sql = self.replace_dependent_parameter(sql)
diff --git a/common/validation/load_modules_from_folder.py b/common/validation/load_modules_from_folder.py
index f95accf..a3a3cb5 100644
--- a/common/validation/load_modules_from_folder.py
+++ b/common/validation/load_modules_from_folder.py
@@ -9,53 +9,54 @@
"""
import importlib.util
import os
+import types
from common.data_extraction.dependent_parameter import DependentParameter
from common.validation import logger
-# from common.environments import Environments
-# from common.data_extraction.data_extractor import DataExtractor
-
-
class LoadModulesFromFolder(DependentParameter):
- def __init__(self):
- super().__init__()
-
- @logger.log_decorator()
- def load_modules_from_folder(self, folder_path):
- """
- 动态加载指定文件夹下的模块,并读取其中的函数
- 通过访问字典的 key 可以获取到对应的函数值并调用。
-
- Args:
- folder_path (str): 要加载模块的文件夹路径
-
- Returns:
- dict: 存储函数的字典,键为函数名,值为函数对象
- """
-
- if not os.path.exists(folder_path): # 检查文件夹路径是否存在
- raise ValueError("Folder path does not exist.")
-
- for file_name in os.listdir(folder_path): # 遍历指定文件夹下的所有文件
- module_name, ext = os.path.splitext(file_name)
- if ext == '.py' and module_name != '__init__': # 如果是 Python 模块文件
- module_path = os.path.join(folder_path, file_name) # 获取模块文件的完整路径
- spec = importlib.util.spec_from_file_location(module_name, module_path)
- module = importlib.util.module_from_spec(spec)
- try:
- spec.loader.exec_module(module) # 加载模块文件并执行其中的代码,将函数定义添加到 module 对象中
- except Exception as e:
- continue
-
- # 遍历 module 对象中的所有属性,找出函数并添加到 functions 字典中
- for name, obj in vars(module).items():
- if callable(obj):
- self.update_environments(name, obj)
+ def __init__(self):
+ super().__init__()
+
+ @logger.log_decorator()
+ def load_modules_from_folder(self, folder_or_mnodule):
+ """
+ 动态加载文件或模块
+ """
+
+ if isinstance(folder_or_mnodule, str):
+ folder_path = folder_or_mnodule
+ if not os.path.exists(folder_path): # 检查文件夹路径是否存在
+ raise ValueError("Folder path does not exist.")
+
+ for file_name in os.listdir(folder_path): # 遍历指定文件夹下的所有文件
+ module_name, ext = os.path.splitext(file_name)
+ if ext == '.py' and module_name != '__init__':
+ module_path = os.path.join(folder_path, file_name) # 获取模块文件的完整路径
+ spec = importlib.util.spec_from_file_location(module_name, module_path)
+ module = importlib.util.module_from_spec(spec)
+ try:
+ spec.loader.exec_module(module) # 加载模块文件并执行其中的代码,将函数定义添加到 module 对象中
+ except:
+ continue
+ for name, obj in vars(module).items():
+ if callable(obj):
+ self.update_environments(name, obj)
+ elif isinstance(folder_or_mnodule, types.ModuleType):
+ module = folder_or_mnodule
+ module = importlib.reload(module)
+ for n, o in vars(module).items():
+ if callable(o):
+ self.update_environments(n, o)
+ else:
+ raise TypeError("folder_or_module should be either a folder path (str) or a module (types.ModuleType).")
if __name__ == '__main__':
- lmff = LoadModulesFromFolder()
- lmff.load_modules_from_folder(r'D:\apk_api\api-test-project\extensions')
- print(lmff.get_environments())
+ lmff = LoadModulesFromFolder()
+ # lmff.load_modules_from_folder(r'..\..\extensions')
+ import extensions as es
+
+ lmff.load_modules_from_folder(es)
+ print(lmff.get_environments())
diff --git a/encryption_rules/__init__.py b/encryption_rules/__init__.py
new file mode 100644
index 0000000..bfb36ca
--- /dev/null
+++ b/encryption_rules/__init__.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+@author: kira
+@contact: 262667641@qq.com
+@file: __init__.py.py
+@time: 2023/8/1 17:07
+@desc:
+"""
diff --git a/extensions/sign.py b/encryption_rules/rules.py
similarity index 97%
rename from extensions/sign.py
rename to encryption_rules/rules.py
index 5bb5729..0ee7d3d 100644
--- a/extensions/sign.py
+++ b/encryption_rules/rules.py
@@ -3,9 +3,9 @@
"""
@author: kira
@contact: 262667641@qq.com
-@file: do_sign.py
+@file: rules.py
@time: 2023/3/14 16:21
-@desc:
+@desc:自定义加密规则
"""
import json
import time
diff --git a/extensions/__init__.py b/extensions/__init__.py
index 6785be3..9875805 100644
--- a/extensions/__init__.py
+++ b/extensions/__init__.py
@@ -12,4 +12,3 @@ from common.log_utils.mylogger import MyLogger
logger = MyLogger()
from .dynamic_scaling_methods import *
-from .sign import *
diff --git a/test_script/test_executor.py b/test_script/test_executor.py
index 1f82f11..b2e149a 100644
--- a/test_script/test_executor.py
+++ b/test_script/test_executor.py
@@ -11,11 +11,10 @@ import unittest
from ddt import ddt, data
-from common import bif_functions
+import extensions
from common.file_handling.do_excel import DoExcel
from common.utils.action import Action
from config import Config
-from extensions import dynamic_scaling_methods
test_file = Config.test_case # 获取 excel 文件路径
excel = DoExcel(test_file)
@@ -26,15 +25,15 @@ test_case, databases, initialize_data, host = excel.get_excel_init_and_cases()
@ddt
class TestProjectApi(unittest.TestCase):
maxDiff = None
- action = Action(initialize_data, bif_functions, databases)
-
+ action = Action(initialize_data, databases)
+
@classmethod
def setUpClass(cls) -> None:
- pass
-
+ cls.action.load_modules_from_folder(extensions)
+
def setUp(self) -> None:
- self.action.set_bif_fun(dynamic_scaling_methods)
-
+ pass
+
@data(*test_case)
def test_api(self, item):
sheet, iid, condition, st, name, desc, h_crypto, r_crypto, method, expected = self.action.base_info(item)
@@ -43,30 +42,30 @@ class TestProjectApi(unittest.TestCase):
regex, keys, deps, jp_dict, ex_request_data = self.action.extractor_info(item)
setup_script, teardown_script = self.action.script(item)
self.action.pause_execution(st)
-
+
# 首执行 sql
self.action.exc_sql(item)
if method.upper() == 'SQL':
self.skipTest("这条测试用例被 SQL 吃了,所以放弃执行了!!")
-
+
# 执行动态代码
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, request_data_type = self.action.request_info(item)
-
+
# 分析请求参数信息
headers, request_data = self.action.analysis_request(request_data, h_crypto, headers, r_crypto, ex_request_data)
result = "PASS"
-
+
# 执行请求操作
kwargs = {request_data_type: request_data, 'headers': headers, "params": query_str}
self.action.send_request(host, url, method, teardown_script, **kwargs)
-
+
try:
# 提取响应
self.action.substitute_data(self.action.response_json, regex=regex, keys=keys, deps=deps, jp_dict=jp_dict)
@@ -77,7 +76,7 @@ class TestProjectApi(unittest.TestCase):
f"\ndeps={deps};"
f"\njp_dict={jp_dict}"
f"\n{err}")
-
+
# 修正断言
expected = self.action.replace_dependent_parameter(expected)
try:
@@ -94,7 +93,7 @@ class TestProjectApi(unittest.TestCase):
# 响应结果及测试结果回写 excel
excel.write_back(sheet_name=sheet, i=iid, response=response, test_result=result,
assert_log=str(self.action.assertions))
-
+
@classmethod
def tearDownClass(cls) -> None:
excel.close_excel()