根据codecheck对代码进行优化

This commit is contained in:
floraachy
2025-12-12 14:38:18 +08:00
parent 59046a6027
commit 0911eeccd4
7 changed files with 184 additions and 166 deletions

View File

@@ -129,7 +129,9 @@ class AssertUtils:
f"assert_type: {assert_type}\n"
f"expect_value: {expect_value}\n"
f"actual_value: {actual_value}\n")
message = message or f"断言 --> 预期结果:{type(expect_value)} || {expect_value} 实际结果:{type(actual_value)} || {actual_value}"
message = message or (f"断言 --> "
f"预期结果:{type(expect_value)} || {expect_value}"
f"实际结果:{type(actual_value)} || {actual_value}")
with allure.step(message):
# 调用utils.assertion_utils.assert_type里面的方法
self.assert_function_mapping[assert_type](expect_value=expect_value, actual_value=actual_value,

View File

@@ -8,8 +8,10 @@
# 标准库导入
from typing import Text
# 第三方库导入
from custom_utils.models import TestCaseEnum, Method, RequestType, Severity
from loguru import logger
# 本地应用/模块导入
from custom_utils.models import TestCaseEnum, Method, RequestType, Severity
class CaseCheckException(Exception):
"""用例检查异常类"""
@@ -91,7 +93,8 @@ class CaseDataCheck:
logger.error(error_msg)
raise CaseCheckException(self.case_id, error_msg)
except Exception as e:
error_msg = f"在处理 {field} 时发生异常需要检查的field_name = {field.value[0]}所有的case_data = {self.case_data},请检查拼写。"
error_msg = (f"在处理 {field} 时发生异常需要检查的field_name = {field.value[0]}"
f"所有的case_data = {self.case_data},请检查拼写。")
raise CaseCheckException(self.case_id, error_msg)
def check_params_right(self, enum_name, attr):

View File

@@ -7,7 +7,7 @@
# 标准库导入
import os
from string import Template
import datetime
from datetime import datetime, timezone
import re
# 第三方库导入
from loguru import logger
@@ -260,7 +260,7 @@ def gen_case_file(filename, case_template_path, config, common_dependence, case_
"func_title": func_name,
# 在测试用例中移除了测试类,直接使用测试方法
# "class_title": class_name,
"now": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
"now": datetime.now(tz=timezone.utc).strftime('%Y-%m-%d %H:%M:%S')
}
)
else:
@@ -295,6 +295,7 @@ def gen_case_file(filename, case_template_path, config, common_dependence, case_
except Exception as e:
logger.error(f"处理用例 {filename} 时发生错误: {str(e)}\n用例数据: {case_data}")
def is_valid_marker(markers):
"""
检查标记名称是否合法:仅支持非数字/下划线开头,由数字,字母,下划线组成的标记名称

View File

@@ -7,7 +7,8 @@
# 标准库导入
import random # 导包不能移除否则random.choice这种就不能处理了
import json
import re, uuid
import re
import uuid
import copy
# 第三方库导入
from string import Template
@@ -48,7 +49,8 @@ class DataHandle:
例如:
原字符串user_id: ${user_id}, user_name: ${user_name}
替换后的原字符串user_id: e1c6fc74-2f21-49a9-8d0c-de16650c6364, user_name: 50c74155-5cb5-4809-bc5d-277addf8c3e7
暂存的需要被处理的关键字或函数:{'e1c6fc74-2f21-49a9-8d0c-de16650c6364': {0: '${user_id}', 1: 'user_id'}, '50c74155-5cb5-4809-bc5d-277addf8c3e7': {0: '${user_name}', 1: 'user_name'}}
暂存的需要被处理的关键字或函数:
{'e1c6fc74-2f21-49a9-8d0c-de16650c6364': {0: '${user_id}', 1: 'user_id'}, '50c74155-5cb5-4809-bc5d-277addf8c3e7': {0: '${user_name}', 1: 'user_name'}}
"""
placeholders = {}
@@ -182,141 +184,141 @@ class DataHandle:
# 声明data_handle方法这样外部就可以直接import data_handle来使用了
data_handle = DataHandle().data_handle
if __name__ == '__main__':
# 下面是测试代码
print("\n----------测试场景1: 识别${python表达式}这里random方法是需要导入random包的---------------------\n")
data = "选择.gitignore: ${random.choice(['Ada', 'Actionscript', 'Ansible', 'Android', 'Agda'])},开源许可证: ${random.choice(['0BSD', 'AAL', 'AFL-1.1', '389-exception'])}"
new = data_handle(data)
print(new, type(new),
end="\n\n---------------------------------------------------------------------------------------------\n\n")
print("-----------测试场景2识别${python表达式},可以在当前文件导入其他模块,一样可以识别替换---------------------")
# 导入其他方法,也可以直接使用
# from common_utils.time_handle import test_fun_a
# data = "${test_fun_a()}"
# if __name__ == '__main__':
# # 下面是测试代码
# print("\n----------测试场景1: 识别${python表达式}这里random方法是需要导入random包的---------------------\n")
# data = "选择.gitignore: ${random.choice(['Ada', 'Actionscript', 'Ansible', 'Android', 'Agda'])},开源许可证: ${random.choice(['0BSD', 'AAL', 'AFL-1.1', '389-exception'])}"
# new = data_handle(data)
# print(new, type(new))
print("\n-----------测试场景3识别FakerData类中的方法---------------------\n")
"""
使用FakerData类中的方法可以直接这样写${generate_random_int()} 也可以带上类名:${FakerData().generate_random_int()}
"""
data = {
"age": "${generate_random_int()}",
"message": "Hello, ${FakerData().generate_female_name()}!",
"nested_data": [
"This is ${name}'s data.",
{
"message": "Age: ${generate_random_int()}",
"nested_list": [
"More data: ${FakerData().generate_random_int()}",
]
}
]
}
new = data_handle(data)
print(new, type(new), end="\n\n")
"""
使用FakerData类中的方法, 支持方法传参使用注意参数如果是str格式建议使用单引号
"""
payload = {
"name": "${generate_name(lan='zh')}",
"repository_name": "${generate_name('zh')}",
"desc": '[[1,2,3,4],"${FakerData().generate_random_int()}"]',
"pre": '[[1,2,3,4],${FakerData().generate_name()}]',
"startTime": "${FakerData.generate_time('%Y-%m-%d')}",
}
new = data_handle(payload)
print(new, type(new), end="\n\n")
"""
还可以直接使用FakerData类中的实例属性
"""
data = {
"payload": {
"en_name": "${faker.name()}", # 这里是使用类FakerData里面的实例属性faker
"zh_name": "${fk_zh.name()}", # 这里是使用类FakerData里面的实例属性fk_zh
"url": "/api/accounts/${FakerData.generate_time('%Y-%m-%d')}/login.json",
}
}
new = data_handle(data)
print(new, type(new), end="\n\n")
"""
FakerData类中没有封装random_name这个方法会无法处理
"""
data = '[[1,2,3,4],"${FakerData().random_name()}"]'
new = data_handle(data)
print(new, type(new),
end="\n\n---------------------------------------------------------------------------------------------\n\n")
print("\n-----------测试场景4识别${}进行关键字替换---------------------\n")
user_info = {
"user_id": 104,
"user_name": "flora"
}
data_03 = "user_id: ${user_id}, user_name: ${user_name}"
new = data_handle(data_03, user_info)
print(new, type(new), end="\n\n")
"""
识别${}进行关键字替换时会保留原值的类型。 比如eval('1,2,4')会变成元组(1,2,4)。经过本方法处理,会保留原有格式
"""
data = {
"winner_id": "${winner_id}",
"user_id": "${user_id}",
"time": "${generate_time()}",
"attachment_ids": "${attachment_ids}",
"assigned_id": "${assigned_id}",
"cookies": "${cookies}"
}
source = {
"winner_id": "1,2,4",
"assigned_id": [],
'报告标题': 'UI自动化测试报告', '项目名称': 'GitLink 确实开源', 'tester': '陈银花',
'department': '开源中心', 'env': 'https://testforgeplus.trustie.net',
'host': 'https://testforgeplus.trustie.net', 'login': 'autotest',
'nickname': 'autotest', 'user_id': 106, 'super_login': 'floraachy', 'super_user_id': 103,
'project_id': '59',
'repo_id': '59', 'project_url': '/autotest/auotest',
'attachment_ids': ['85b7f7ff-59e6-4f38-88da-29440aa4fc18', 'ba23f9b1-ad92-476d-ac4d-aba1382a9636'],
'file_name': 'gitlinklogo3.jpg',
'cookies': '{"_educoder_session": "d79e0e75f71cd98a9df2665d405b49e7", "autologin_trustie": "d25b412c26388182a50e8be38e4b9731c4e783ba"}',
}
new = data_handle(obj=data, source=source)
print(new, type(new),
end="\n\n---------------------------------------------------------------------------------------------\n\n")
print("\n-----------测试场景5识别 字符串里面是python表达式的情况---------------------\n")
data = [
"[1,2,3,4]", "1+1", "[1, '1', [1, 2], {'name':'flora', 'age': '1'}]"
]
new = data_handle(data)
print(new, type(new),
end="\n\n---------------------------------------------------------------------------------------------\n\n")
print("\n-----------测试场景5导入的函数---------------------\n")
source = {
"added_testcase_test_step": [
{'id': 5878, 'index': 0, 'content': '科技-大学', 'expectedResult': '一直-有些', 'execResult': 0},
{'id': 5879, 'index': 1, 'content': '包括-质量', 'expectedResult': '系统-发表', 'execResult': 0}],
"test_ids": [1, 2, 3, 4, 5]
}
data = {
"testcaseStepList": "${data_keys_to_keep(${added_testcase_test_step},'id')}"}
new = data_handle(obj=data, source=source)
print(new, type(new),
end="\n\n---------------------------------------------------------------------------------------------\n\n")
data = {
"test_ids": '${list_to_str(target=${test_ids})}'
}
new = data_handle(obj=data, source=source)
print(new, type(new),
end="\n\n---------------------------------------------------------------------------------------------\n\n")
# print(new, type(new),
# end="\n\n---------------------------------------------------------------------------------------------\n\n")
#
# print("-----------测试场景2识别${python表达式},可以在当前文件导入其他模块,一样可以识别替换---------------------")
# # 导入其他方法,也可以直接使用
# # from common_utils.time_handle import test_fun_a
# # data = "${test_fun_a()}"
# # new = data_handle(data)
# # print(new, type(new))
#
# print("\n-----------测试场景3识别FakerData类中的方法---------------------\n")
# """
# 使用FakerData类中的方法可以直接这样写${generate_random_int()} 也可以带上类名:${FakerData().generate_random_int()}
# """
# data = {
# "age": "${generate_random_int()}",
# "message": "Hello, ${FakerData().generate_female_name()}!",
# "nested_data": [
# "This is ${name}'s data.",
# {
# "message": "Age: ${generate_random_int()}",
# "nested_list": [
# "More data: ${FakerData().generate_random_int()}",
# ]
# }
# ]
# }
# new = data_handle(data)
# print(new, type(new), end="\n\n")
#
# """
# 使用FakerData类中的方法, 支持方法传参使用注意参数如果是str格式建议使用单引号
# """
# payload = {
# "name": "${generate_name(lan='zh')}",
# "repository_name": "${generate_name('zh')}",
# "desc": '[[1,2,3,4],"${FakerData().generate_random_int()}"]',
# "pre": '[[1,2,3,4],${FakerData().generate_name()}]',
# "startTime": "${FakerData.generate_time('%Y-%m-%d')}",
# }
# new = data_handle(payload)
# print(new, type(new), end="\n\n")
#
# """
# 还可以直接使用FakerData类中的实例属性
# """
#
# data = {
# "payload": {
# "en_name": "${faker.name()}", # 这里是使用类FakerData里面的实例属性faker
# "zh_name": "${fk_zh.name()}", # 这里是使用类FakerData里面的实例属性fk_zh
# "url": "/api/accounts/${FakerData.generate_time('%Y-%m-%d')}/login.json",
# }
# }
#
# new = data_handle(data)
# print(new, type(new), end="\n\n")
#
# """
# FakerData类中没有封装random_name这个方法会无法处理
# """
# data = '[[1,2,3,4],"${FakerData().random_name()}"]'
# new = data_handle(data)
# print(new, type(new),
# end="\n\n---------------------------------------------------------------------------------------------\n\n")
#
# print("\n-----------测试场景4识别${}进行关键字替换---------------------\n")
# user_info = {
# "user_id": 104,
# "user_name": "flora"
# }
# data_03 = "user_id: ${user_id}, user_name: ${user_name}"
# new = data_handle(data_03, user_info)
# print(new, type(new), end="\n\n")
#
# """
# 识别${}进行关键字替换时会保留原值的类型。 比如eval('1,2,4')会变成元组(1,2,4)。经过本方法处理,会保留原有格式
# """
# data = {
# "winner_id": "${winner_id}",
# "user_id": "${user_id}",
# "time": "${generate_time()}",
# "attachment_ids": "${attachment_ids}",
# "assigned_id": "${assigned_id}",
# "cookies": "${cookies}"
# }
# source = {
# "winner_id": "1,2,4",
# "assigned_id": [],
# '报告标题': 'UI自动化测试报告', '项目名称': 'GitLink 确实开源', 'tester': '陈银花',
# 'department': '开源中心', 'env': 'https://testforgeplus.trustie.net',
# 'host': 'https://testforgeplus.trustie.net', 'login': 'autotest',
# 'nickname': 'autotest', 'user_id': 106, 'super_login': 'floraachy', 'super_user_id': 103,
# 'project_id': '59',
# 'repo_id': '59', 'project_url': '/autotest/auotest',
# 'attachment_ids': ['85b7f7ff-59e6-4f38-88da-29440aa4fc18', 'ba23f9b1-ad92-476d-ac4d-aba1382a9636'],
# 'file_name': 'gitlinklogo3.jpg',
# 'cookies': '{"_educoder_session": "d79e0e75f71cd98a9df2665d405b49e7", "autologin_trustie": "d25b412c26388182a50e8be38e4b9731c4e783ba"}',
# }
#
# new = data_handle(obj=data, source=source)
# print(new, type(new),
# end="\n\n---------------------------------------------------------------------------------------------\n\n")
#
# print("\n-----------测试场景5识别 字符串里面是python表达式的情况---------------------\n")
# data = [
# "[1,2,3,4]", "1+1", "[1, '1', [1, 2], {'name':'flora', 'age': '1'}]"
# ]
# new = data_handle(data)
# print(new, type(new),
# end="\n\n---------------------------------------------------------------------------------------------\n\n")
#
# print("\n-----------测试场景5导入的函数---------------------\n")
# source = {
# "added_testcase_test_step": [
# {'id': 5878, 'index': 0, 'content': '科技-大学', 'expectedResult': '一直-有些', 'execResult': 0},
# {'id': 5879, 'index': 1, 'content': '包括-质量', 'expectedResult': '系统-发表', 'execResult': 0}],
# "test_ids": [1, 2, 3, 4, 5]
# }
# data = {
# "testcaseStepList": "${data_keys_to_keep(${added_testcase_test_step},'id')}"}
#
# new = data_handle(obj=data, source=source)
# print(new, type(new),
# end="\n\n---------------------------------------------------------------------------------------------\n\n")
#
# data = {
# "test_ids": '${list_to_str(target=${test_ids})}'
# }
#
# new = data_handle(obj=data, source=source)
# print(new, type(new),
# end="\n\n---------------------------------------------------------------------------------------------\n\n")

View File

@@ -54,11 +54,10 @@ def get_file_content(file_name):
def list_to_str(target):
"""
将列表中的元素转换为字符串,并用逗号分隔。
:param target: 要转换为字符串的列表
:return: 以逗号分隔的字符串。
"""
将列表中的元素转换为字符串,并用逗号分隔。
:param target: 要转换为字符串的列表。
:return: 以逗号分隔的字符串
"""
if isinstance(target, list) and target:
# 过滤掉列表中的None值
filtered_list = [str(item) for item in target if item is not None]

View File

@@ -66,7 +66,8 @@ def response_extract(response: Response, expr: str = '.'):
"""
从response响应对象提取cookies之类
:param response : response对象
:param expr: 提取表达式。部分参考response.status_code response.cookies, response.text, response.headers, response.is_redirect
:param expr: 提取表达式。
部分参考response.status_code response.cookies, response.text, response.headers, response.is_redirect
:return result: 提取的结果,未提取到返回 None
"""
try:

View File

@@ -19,7 +19,7 @@ from settings import FILES_DIR
from custom_utils.requests_utils.base_request import BaseRequest
from custom_utils.data_utils.data_handle import data_handle
from custom_utils.data_utils.extract_data_handle import json_extractor, re_extract, response_extract
from common_utils.files_utils.files_handle import get_files,load_yaml_file
from common_utils.files_utils.files_handle import get_files, load_yaml_file
from custom_utils.assertion_utils.assert_control import AssertHandle
from custom_utils.report_utils.allure_handle import allure_step
from common_utils.database_utils.mysql_handle import MysqlServer
@@ -117,24 +117,34 @@ class RequestControl(BaseRequest):
f"cookies参数要求是Dict or CookieJar object 目前cookies类型是{type(cookies)} cookies值是{cookies}")
@staticmethod
def headers_handle(headers: dict, source: dict = None):
def headers_handle(headers: dict = None, source: dict = None) -> dict:
"""
headers里面传Cookie要求Cookie类型是str
Args:
headers: 请求头字典,默认为空字典
source: 数据源
Returns:
dict: 处理后的请求头字典
"""
if headers:
# 从用例数据中获取header 处理header
headers = data_handle(obj=headers, source=source)
# 如果请求头中有cookies需要进行单独处理
if headers.get("Cookie", None):
cookies = headers["Cookie"]
if isinstance(cookies, dict):
headers["Cookie"] = '; '.join([f"{key}={value}" for key, value in cookies.items()])
if isinstance(cookies, http.cookiejar.CookieJar):
cookies_dict = utils.dict_from_cookiejar(cookies)
headers["Cookie"] = '; '.join([f"{key}={value}" for key, value in cookies_dict.items()])
if isinstance(cookies, str):
headers["Cookie"] = cookies
return headers
if headers is None:
headers = {}
# 从用例数据中获取header处理header
headers = data_handle(obj=headers, source=source)
# 处理Cookie字段
if headers.get("Cookie"):
cookies = headers["Cookie"]
if isinstance(cookies, dict):
headers["Cookie"] = '; '.join([f"{key}={value}" for key, value in cookies.items()])
elif isinstance(cookies, http.cookiejar.CookieJar):
cookies_dict = utils.dict_from_cookiejar(cookies)
headers["Cookie"] = '; '.join([f"{key}={value}" for key, value in cookies_dict.items()])
# str类型不需要处理保持原样
return headers
@staticmethod
def files_handle(files: str, source: dict = None):