根据codecheck对代码进行优化
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
"""
|
||||
检查标记名称是否合法:仅支持非数字/下划线开头,由数字,字母,下划线组成的标记名称
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user