addproject

This commit is contained in:
qiaoxinjiu
2026-01-22 19:10:37 +08:00
commit 6994b185a3
184 changed files with 21039 additions and 0 deletions

View File

@@ -0,0 +1,851 @@
# -*- coding:utf-8 -*-
import copy
import importlib
import json
import os
import random
import re
import sys
import string
import time
import traceback
def get_project_root_path(path="base_framework"):
"""
获取项目目录
"""
o_path = os.getcwd()
try:
project_path = re.search(r"(.*%s)" % path, o_path).group(1)
return os.path.abspath(os.path.join(project_path, os.path.pardir))
except:
pass
Project_Path = get_project_root_path()
sys.path.append(Project_Path)
from base_framework.platform_tools.Keywords_service.keyword_service import SetAttr, log
def load_module_from_file(file_path, team):
module_file = re.search(r"\\(%s\\.*)\.py" % team, file_path)
# if not module_file:
# module_file = re.search(r"\\(%s\\.*)\.py" % team.lower(), file_path)
temp = module_file.group(1)
temp = temp.replace(os.sep, ".")
# try:
# module = importlib.import_module(temp)
# except Exception as err:
# temp = re.sub(r"%s\." % team, "%s." % team.lower(), temp)
# module = importlib.import_module(temp)
return importlib.import_module(temp)
class ITCaseFileOperation(object):
def __init__(self, team, kw_instance):
self.kw = kw_instance
self.all_url = kw_instance.all_url
self.kw_class_name = kw_instance.kw_class
self.case_dir = os.path.abspath(os.path.join(Project_Path, team, "test_case", "TestCase", "1.接口"))
self.env_path = os.path.abspath(
os.path.join(Project_Path, team, "test_case", "Resource", "AdapterKws", "env.robot"))
def _check_case_file_exist(self, file_path):
if os.path.exists(file_path) and os.path.isfile(file_path):
return True
else:
return False
def check_case_exist(self, case_path, case_name):
if self._check_case_file_exist(case_path):
with open(case_path, "r", encoding="utf-8") as f:
for line in f.readlines():
if line.startswith(case_name):
return True
else:
return False
else:
return False
def generate_case_file(self, file_path):
dirname = file_path[:-len(os.path.basename(file_path))]
if not self._check_case_file_exist(file_path):
if not os.path.exists(dirname):
os.makedirs(dirname)
self.write_content_to_case_file(file_path, self.generate_env_releate_path(dirname))
else:
with open(file_path, "r", encoding="utf-8") as f:
content = f.readlines()
if content:
if "\n" != content[-1]:
self.write_content_to_case_file(file_path, "\n")
else:
self.write_content_to_case_file(file_path, self.generate_env_releate_path(dirname))
def generate_env_releate_path(self, file_path):
return "*** Settings ***\nResource " + os.path.relpath(self.env_path,
file_path).replace("\\",
"/") + "\n\n*** Test Cases ***\n"
def _check_case_file_resource(self, file_path):
"""
确定case文件中是否有关键字
"""
with open(file_path, "a+", encoding="utf-8") as f:
content_list = f.readlines()
if "*** Keywords ***\n" not in content_list:
return True
else:
kw_index = content_list.rindex("*** Keywords ***\n")
for index in range(kw_index, len(content_list) + 1):
if "*** Test Cases ***\n" == content_list[index]:
status = True
if "*** Keywords ***\n" == content_list[index]:
status = False
return status
def write_content_to_case_file(self, file_path, content):
status = self._check_case_file_resource(file_path)
with open(file_path, "a+", encoding="utf-8") as f:
if status:
f.write(content)
else:
content = "*** Test Cases ***\n" + content
f.write(content)
class ITCaseContentOperation(object):
def __init__(self, team, kw_instance):
self.team = team
self.file = ITCaseFileOperation(team, kw_instance)
self.doc_content_row_temp = " ... | {} | {} | {} |"
self.normal_1001 = None
self.un_expect_list = None
self.case_string = None
def _generate_case_name(self, interface_name, case_type, case_des):
return "-".join([interface_name, case_type, case_des])
def _check_interface_confirm(self, interface_info):
if not interface_info.confirmed:
raise Exception("接口%s未确认,请先确认接口参数。" % interface_info.name)
def generate_case_body_all_1001_array(self, request_demo, parameters):
temp_list = list()
demo_copy = copy.deepcopy(request_demo)
for key, value in request_demo.items():
if not value:
demo_copy.pop(key)
if len(demo_copy.keys()) == 1:
demo_copy = demo_copy.pop(list(demo_copy.keys())[0])
dict_para, self.un_expect_list, _, _ = self._analysis_case_parameters_to_dict(parameters)
demo_add_values = self._analysis_case_parameters_to_value(demo_copy, dict_para)
data_list = self._analysis_dict_to_body_value(demo_copy, demo_add_values)
if isinstance(demo_copy, list):
for item in data_list:
temp_list.append([item])
data_list = temp_list
return data_list
def _generate_parameter_to_dict(self, parameters):
dict_temp = dict()
for parameter in parameters:
parameter_attr = SetAttr(parameter)
dict_temp[parameter_attr.name] = parameter_attr
return dict_temp
def _analysis_case_parameters_to_value_empty_dict(self, request_demo, parameters, type=None):
"""
循环生成缺少某个参数的值,其它正确的参数组合列表
"""
parameter_expect_list = list()
expect_lenth = 0
un_expect_lenth = 0
parameter_expect_dict = dict()
parameter_un_expect_dict = dict()
for key, parameter_attr in parameters.items():
if parameter_attr.normal_values:
parameter_expect_dict[parameter_attr.name] = parameter_attr.normal_values.split(",")
else:
parameter_expect_dict[parameter_attr.name] = [
self._generate_body_expect_type_value(parameter_attr.type)]
if len(parameter_expect_dict[parameter_attr.name]) > expect_lenth:
expect_lenth = len(parameter_expect_dict[parameter_attr.name])
if parameter_attr.exception_values:
parameter_un_expect_dict[parameter_attr.name] = parameter_attr.exception_values.split(",")
else:
parameter_un_expect_dict[parameter_attr.name] = [
self._generate_body_un_expect_type_value(parameter_attr.type)]
if len(parameter_un_expect_dict[parameter_attr.name]) > un_expect_lenth:
un_expect_lenth = len(parameter_un_expect_dict[parameter_attr.name])
for key in parameter_expect_dict.keys():
if key not in json.dumps(request_demo):
continue
value = copy.copy(parameter_expect_dict)
value[key] = ['NULL']
if parameters.get(key).is_need == 1:
status = "FAIL"
else:
status = "PASS"
if type == "1102":
name = "缺少参数%s" % key
else:
name = "缺少参数%s的值" % key
parameter_expect_list.append([value, status, name])
return parameter_expect_list
def _distinguish_parameters_by_is_needed(self, parameters):
"""
将必填参数和非必须参数分开成2个列表
"""
need_parameters = list()
no_need_parameters = list()
for parameter in parameters:
parameter_attr = SetAttr(parameter)
if parameter_attr.is_need != 0:
need_parameters.append(parameter_attr)
else:
no_need_parameters.append(parameter_attr)
return need_parameters, no_need_parameters
def _replace_null_value_no_need_parameters(self, demo, no_need_parameter_attrs):
"""
将所有非必填参数置空
"""
really_body = copy.deepcopy(demo)
for parameter_attr in no_need_parameter_attrs:
if re.search(r"\"%s\"" % parameter_attr.name, demo):
check_para = r"\"%s\":\s[\[\{]" % parameter_attr.name
if re.search(check_para, demo):
continue
try:
expect_value = parameter_attr.normal_values.split(",")[0]
except Exception as err:
log.error(err)
raise Exception("接口参数%s无正常值,请先确认接口参数。" % parameter_attr.name)
patten1 = r"\"%s\":\s\"%s\"" % (parameter_attr.name, expect_value)
replace1 = "\"%s\": \"NULL\"" % parameter_attr.name
really_body = re.sub(patten1, replace1, really_body)
return really_body
def generate_case_body_all_1101_array(self, request_demo, parameters):
"""
生成1101用例对应的所有请求参数组合
"""
body_array = list()
need, no_need = self._distinguish_parameters_by_is_needed(parameters)
demo_json = json.dumps(request_demo, ensure_ascii=False)
if no_need:
no_need_demo_json = self._replace_null_value_no_need_parameters(demo_json, no_need)
body_array.append([json.loads(no_need_demo_json), "PASS", "所有非必填参数为空"])
for item in need:
parameter_attr = copy.copy(item)
demo_json_copy = copy.copy(demo_json)
if re.search("\"%s\"" % parameter_attr.name, demo_json_copy):
check_para = r"\"%s\":\s\{|\"%s\":\s\[\{" % (parameter_attr.name, parameter_attr.name)
if re.search(check_para, demo_json_copy):
continue
name = "缺少参数%s" % parameter_attr.name
log.info("1101%s" % name)
try:
expect_value = parameter_attr.normal_values.split(",")[0]
except Exception as err:
log.error(err)
raise Exception("接口参数%s无正常值,请先确认接口参数。" % parameter_attr.name)
if parameter_attr.type == "array":
patten1 = r"\"%s\":\s\[\"%s\"\]" % (parameter_attr.name, expect_value)
replace1 = "\"%s\": []" % parameter_attr.name
else:
patten1 = r"\"%s\":\s\"%s\"" % (parameter_attr.name, expect_value)
patten1 = patten1.replace("{", r"\{")
patten1 = patten1.replace("}", r"\}")
patten1 = patten1.replace("[", r"\[")
patten1 = patten1.replace("]", r"\]")
patten1 = patten1.replace("$", r"\$")
replace1 = "\"%s\": \"NULL\"" % parameter_attr.name
really_body = re.sub(patten1, replace1, demo_json_copy)
if parameter_attr.is_need == 1:
status = "FAIL"
else:
status = "PASS"
body_array.append([json.loads(really_body), status, name])
return body_array
def _clean_all_none_json_char(self, really_body):
"""
清除1102场景删除缺少参数后不规则的字符串内容
"""
really_body = re.sub(",\s,", ",", really_body)
really_body = re.sub("\[\s?,", "[", really_body)
really_body = re.sub("\{\s?,", "{", really_body)
really_body = re.sub(",\s\]", "]", really_body)
really_body = re.sub(",\s\}", "}", really_body)
really_body = re.sub("\s,", "", really_body)
return really_body
def _replace_null_all_no_need_parameters(self, demo, no_need_parameter_attrs):
"""
将所有非必填参数置空
"""
really_body = copy.deepcopy(demo)
for parameter_attr in no_need_parameter_attrs:
if re.search(r"\"%s\"" % parameter_attr.name, demo):
check_para = r"\"%s\":\s\{|\"%s\":\s\[\{" % (parameter_attr.name, parameter_attr.name)
if re.search(check_para, demo):
continue
try:
expect_value = parameter_attr.normal_values.split(",")[0]
except Exception as err:
log.error(err)
raise Exception("接口参数%s无正常值,请先确认接口参数。" % parameter_attr.name)
if parameter_attr.type == "array":
patten1 = r"\"%s\":\s\[\"%s\"\]" % (parameter_attr.name, expect_value)
else:
patten1 = r"\"%s\":\s\"%s\"" % (parameter_attr.name, expect_value)
replace1 = ""
really_body = re.sub(patten1, replace1, really_body)
really_body = self._clean_all_none_json_char(really_body)
return really_body
def generate_case_body_all_1102_array(self, request_demo, parameters):
"""
生成1102用例对应的所有参数组合
"""
body_array = list()
need, no_need = self._distinguish_parameters_by_is_needed(parameters)
demo_json = json.dumps(request_demo, ensure_ascii=False)
if no_need:
no_need_demo_json = self._replace_null_all_no_need_parameters(demo_json, no_need)
body_array.append([json.loads(no_need_demo_json), "PASS", "所有非必填参数均缺失"])
for item in need:
parameter_attr = copy.copy(item)
demo_json_copy = copy.copy(demo_json)
if re.search(r"\"%s\"" % parameter_attr.name, demo_json_copy):
check_para = r"\"%s\":\s\{|\"%s\":\s\[\{" % (parameter_attr.name, parameter_attr.name)
if re.search(check_para, demo_json_copy):
continue
name = "缺少参数%s" % parameter_attr.name
log.info("1102%s" % name)
expect_value = parameter_attr.normal_values.split(",")[0]
if parameter_attr.type == "array":
patten1 = r"\"%s\":\s\[\"%s\"\]" % (parameter_attr.name, expect_value)
else:
patten1 = r"\"%s\":\s\"%s\"" % (parameter_attr.name, expect_value)
patten1 = patten1.replace("{", r"\{")
patten1 = patten1.replace("}", r"\}")
patten1 = patten1.replace("[", r"\[")
patten1 = patten1.replace("]", r"\]")
patten1 = patten1.replace("$", r"\$")
replace1 = ""
really_body = re.sub(patten1, replace1, demo_json_copy)
really_body = self._clean_all_none_json_char(really_body)
if parameter_attr.is_need == 1:
status = "FAIL"
else:
status = "PASS"
body_array.append([json.loads(really_body), status, name])
return body_array
def generate_case_body_all_1201_array(self, request_demo, parameters):
"""
生成1201用例对应的所有参数组合
"""
body_array = list()
demo_json = json.dumps(request_demo, ensure_ascii=False)
for item in parameters:
parameter_attr = SetAttr(item)
if re.search(r"\"%s\"" % parameter_attr.name, demo_json):
check_para = r"\"%s\":\s\{|\"%s\":\s\[\{" % (parameter_attr.name, parameter_attr.name)
if re.search(check_para, demo_json):
continue
log.info("参数%s开始替换异常值" % parameter_attr.name)
for un_expect_item in self.un_expect_list.get(parameter_attr.name, []):
name = "参数%s使用异常值%s" % (parameter_attr.name, un_expect_item)
demo_json_copy = copy.copy(demo_json)
expect_value = parameter_attr.normal_values.split(",")[0]
if parameter_attr.type == "array":
patten1 = r"\"%s\":\s\[\"%s\"\]" % (parameter_attr.name, expect_value)
replace1 = '"%s": ["%s"]' % (parameter_attr.name, un_expect_item)
else:
patten1 = r"\"%s\":\s\"%s\"" % (parameter_attr.name, expect_value)
patten1 = patten1.replace("{", r"\{")
patten1 = patten1.replace("}", r"\}")
patten1 = patten1.replace("[", r"\[")
patten1 = patten1.replace("]", r"\]")
patten1 = patten1.replace("$", r"\$")
replace1 = '"%s": "%s"' % (parameter_attr.name, un_expect_item)
really_body = re.sub(patten1, replace1, demo_json_copy)
status = "FAIL"
body_array.append([json.loads(really_body), status, name])
return body_array
def create_case_content(self, result_path, interface_info, parameters, demo, case_type, tags=None):
"""
生成用例的所有内容
"""
self._check_interface_confirm(interface_info)
body_content = list()
doc = self.generate_case_doc(interface_info, tags=tags, demo=demo)
case_file, _ = self.generate_case_file_path(interface_info)
interface_name = interface_info.name
if not parameters:
body = self.generate_case_body_content(interface_info.in_url, doc, interface_name, case_type,
interface_info.interface_describe, None, status="PASS")
else:
try:
body_array = self.generate_case_body_all_1001_array(demo, parameters)
self.normal_1001 = body_array[0]
except TypeError:
log.warning(traceback.print_exc())
body_array = []
self.normal_1001 = {}
if case_type == "1001":
try:
body = self.generate_case_body_content(interface_info.in_url, doc, interface_name, case_type,
interface_info.interface_describe, body_array, status="PASS")
except Exception as err:
msg = "生成用例%s,%s失败原因如下:%s" % (interface_info.type, interface_info.in_url, traceback.print_exc())
log.error(msg)
self.file.write_content_to_case_file(result_path, msg + "\n")
elif case_type == "1101" or case_type == "1102" or case_type == "1201":
body_temp_list = []
# parameters_temp = self._generate_parameter_to_dict(parameters)
try:
body_array = eval(
"self.generate_case_body_all_%s_array(self.normal_1001, parameters)" % case_type)
if case_type == "1101":
name = "缺少参数值"
elif case_type == "1102":
name = "缺少参数key和值"
elif case_type == "1201":
name = "参数使用异常值"
else:
name = ""
body_tmp = self.generate_case_body_content(interface_info.in_url, doc, interface_name,
case_type,
name, body_array, status="PASS")
body_temp_list.append(body_tmp)
body = "".join(body_temp_list)
except Exception as err:
msg = "生成用例%s,%s失败原因如下:%s" % (interface_info.type, interface_info.in_url, traceback.print_exc())
log.error(msg)
self.file.write_content_to_case_file(result_path, msg + "\n")
raise err
body_content.append(body)
self.file.write_content_to_case_file(case_file, "\n".join(body_content))
msg = "接口url%s,%s,生成case%s成功!路径为:%s" % (interface_info.type, interface_info.in_url, case_type, case_file)
log.info(msg)
self.file.write_content_to_case_file(result_path, msg + "\n")
return msg
def generate_case_body_content(self, url, doc, interface_name, case_type, description, body_para, status="PASS"):
body_content = list()
case_name = self._generate_case_name(interface_name, case_type, description)
body_content.append(case_name)
body_content.append(doc)
# 如何需要自动生成1001类型用例的请求body数据请将304/305行放开并把306~310注释
request = self._generate_case_body_content(url, body_content=body_para, status=status)
body_content.append(request)
# if case_type != "1001":
# request = self._generate_case_body_content(url, body_content=body_para, status=status)
# body_content.append(request)
# else:
# body_content.append(" #请自行添加用例请求数据!\n")
return "\n".join(body_content)
def _generate_case_body_content(self, url, body_content=None, status="PASS"):
body_list = []
if body_content is None:
try:
body_request = " ${resp} %s" % (self.file.all_url.get(url)[1])
except Exception as err:
log.error(traceback.print_exc())
body_request = " #url: %s 无法找到对应的关键字,请检查并更新!" % url
body_list.append(body_request)
body_list.append(" Log ${resp}")
if self.team.upper() in ["TMO"]:
body_validate_success = " should be equal as json ${resp} %s" % '请自行添加检查结果'
else:
body_validate_code = " Should Be Equal ${resp['code']} ${200}"
body_validate_success = " Should Be True ${resp['success']}"
body_list.append(body_validate_code)
body_list.append(body_validate_success)
else:
if not body_content:
body_create = " #request_demo无内容或者parameters在数据表中不全请先检查再生成 \n ${body} Evaluate %s" % body_content
body_list.append(body_create)
count = 0
for real_body in body_content:
body_error = None
result = {"message": "", "code": 200, "success": True}
temp = copy.copy(real_body)
if len(real_body) == 3 and isinstance(real_body, list):
if real_body[1] == "PASS" or real_body[1] == "FAIL":
real_body = temp[0]
status = temp[1]
case_description = temp[2]
body_list.append(" #%s" % case_description)
try:
module = load_module_from_file(self.file.kw.kw_file_path, self.team)
importlib.reload(module)
if isinstance(real_body, list):
temp_type = "*"
else:
temp_type = "**"
result = eval(
"%s.%s().%s(%sreal_body)" % (
"module", self.file.kw_class_name, self.file.all_url.get(url)[1], temp_type))
except:
msg = "#url: %s 无法通过参数得到请求结果!" % url
log.warning(real_body)
log.warning(msg)
log.warning(traceback.print_exc())
if "${time}" in str(real_body):
body_list.append(" ${time} get time epoch")
body_create = " ${body_%s} Evaluate %s" % (count, real_body)
try:
if isinstance(real_body, list):
body_request = " ${resp_%s} %s %s" % (
count, self.file.all_url.get(url)[1], "@{body_%s}" % count)
elif isinstance(real_body, dict):
body_request = " ${resp_%s} %s %s" % (
count, self.file.all_url.get(url)[1], "&{body_%s}" % count)
except Exception as err:
log.error(traceback.print_exc())
body_request = " #url: %s 无法找到对应的关键字,请检查并更新!" % url
body_list.append(body_create)
body_list.append(body_request)
body_list.append(" Log ${resp_%s}" % count)
if self.team.upper() in ["TMO"]:
body_validate_resp = " Should Be Equal as json ${resp_%s} %s" % (count, result)
else:
try:
body_validate_code = " Should Be Equal as strings ${resp_%s['code']} ${%s}"
# body_validate_success = " %s ${resp_%s['success']}"
body_validate_success = " %s ${resp_%s['success']} %s"
body_validate_resp = " %s ${resp_%s[\"message\"]} %s"
if isinstance(result, str):
body_validate_code = " #特殊接口返回!"
body_validate_success = " #返回为bytes类型的字符码。仅检查结果是否相等"
body_validate_resp = " Should Be Equal as strings ${resp_%s} %s" % (count, result)
elif status == "PASS":
body_validate_code = body_validate_code % (count, result['code'])
body_validate_success = body_validate_success % ("Should Be True", count, "")
try:
if result["message"]:
body_validate_resp = body_validate_resp % (
"Should Be Equal as strings", count, result["message"])
else:
body_validate_resp = body_validate_resp % (
"Should Be Equal as strings", count, '${EMPTY}')
except KeyError as err:
body_validate_resp = " #resp中没有message请后续自行添加"
log.warning(err)
log.warning("resp中没有message请后续自行添加")
else:
try:
body_validate_code = body_validate_code % (count, result['code'])
except Exception as e:
if "status" in result:
body_validate_code = body_validate_code % (count, result['status'])
body_validate_code = body_validate_code.replace("code", "status")
else:
raise KeyError("接口不中无code返回请与开发确认")
try:
body_validate_success = body_validate_success % (
"Should Be Equal As Strings", count, result["success"])
except Exception as err:
if "error" in result:
body_validate_success = body_validate_success % (
"Should Be Equal As Strings", count, result["error"])
body_validate_success = body_validate_success.replace("success", "error")
else:
raise KeyError("接口不中无success返回请与开发确认")
try:
if result.get("message"):
if re.search("[a-zA-Z0-9]{32}", result.get("message", "")):
body_validate_resp = body_validate_resp % ("should contain", count,
re.sub("[a-zA-Z0-9]{32}", "", result["message"]))
else:
body_validate_resp = body_validate_resp % (
"should be equal as strings", count, result["message"])
else:
body_validate_resp = body_validate_resp % (
"Should Be Equal as strings", count, '${EMPTY}')
except KeyError as err:
body_validate_resp = " #resp中没有message请后续自行添加"
log.warning(err)
log.warning("resp中没有message请后续自行添加")
except Exception as error:
log.error(error)
body_validate_code = None
body_validate_success = None
body_validate_resp = None
body_error = " #无法正确生成异常用例返回值,请检查并手动生成!"
if body_validate_code:
body_list.append(body_validate_code)
if body_validate_success:
body_list.append(body_validate_success)
if body_validate_resp:
body_list.append(body_validate_resp)
if body_error:
body_list.append(body_error)
# body_list.append(" #请自行添加data校验")
count += 1
body_list.append("\n")
return "\n".join(body_list)
def _generate_body_expect_type_value(self, type):
if type.lower() == 'integer':
value = random.randint(0, 100)
elif type.lower() == "string":
value = "".join([random.choice(string.digits + string.ascii_letters) for i in range(5)])
elif type.lower() == "date":
value = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
elif type.lower() == "boolean":
value = True
elif type.lower() == "array":
value = [1]
else:
value = "123"
return value
def _generate_body_un_expect_type_value(self, type):
value = ""
if type.lower() == 'integer':
value = "".join([random.choice(string.digits + string.ascii_letters) for i in range(5)])
elif type.lower() == "string":
value = random.randint(0, 10000)
else:
value = False
return value
def _analysis_dict_to_body_value(self, dict_none, dict_data):
"""
生成所有请求参数的组合列表
"""
data_list = []
if isinstance(dict_none, list):
if dict_none:
for index in range(len(dict_none)):
data = self._analysis_dict_to_body_value(dict_none[index], dict_data[index])
data_list.extend(data)
else:
data_list = dict_data
elif isinstance(dict_none, dict):
try:
len_num = self._get_nums(dict_data)
except Exception as e:
# log.error(e)
log.error("数据表request_parameters中参数不全请使用interface_hunter补全参数")
raise e
for i in range(0, len_num):
copy_dict = copy.copy(dict_none)
for key, value in copy_dict.items():
data = self._analysis_dict_to_body_value(copy_dict[key], dict_data[key])
if not data:
copy_dict[key] = None
elif i >= len(data):
copy_dict[key] = data[0]
if isinstance(value, list):
copy_dict[key] = [data[0]]
else:
copy_dict[key] = data[i]
if isinstance(value, list):
copy_dict[key] = [data[i]]
data_list.append(copy_dict)
else:
data_list = dict_data
return data_list
def _get_nums(self, dict_data):
"""
获取所有参数对应值的最大长度
"""
nums_list = [0]
if isinstance(dict_data, list):
for item in dict_data:
if isinstance(item, dict):
data = self._get_nums(dict_data[0])
nums_list.append(data)
else:
nums_list.append(len(dict_data))
elif isinstance(dict_data, dict):
for value in dict_data.values():
data = self._get_nums(value)
nums_list.append(data)
elif dict_data == None:
nums_list.append(0)
else:
nums_list.append(len(dict_data))
return max(nums_list)
def _analysis_case_parameters_to_value(self, interface_demo, parameters):
"""
根据demo将每个参数的对应值的列表写回demo
"""
body = copy.copy(interface_demo)
if isinstance(body, list):
for index in range(len(body)):
item = body[index]
body[index] = self._analysis_case_parameters_to_value(item, parameters)
elif isinstance(body, dict):
for key, value in body.items():
if isinstance(value, dict) or isinstance(value, list):
if value:
body[key] = self._analysis_case_parameters_to_value(body.get(key), parameters)
else:
body[key] = parameters.get(key)
else:
body[key] = parameters.get(key)
return body
def _analysis_case_parameters_to_dict(self, parameters):
"""
根据所有参数生成正常值 和异常值的列表
"""
expect_lenth = 0
un_expect_lenth = 0
parameter_expect_dict = dict()
parameter_un_expect_dict = dict()
for parameter in parameters:
parameter_attr = SetAttr(parameter)
if parameter_attr.normal_values:
if parameter_attr.normal_values.startswith("["):
parameter_expect_dict[parameter_attr.name] = parameter_attr.normal_values.split(",")
else:
if parameter_attr.type == "array":
parameter_expect_dict[parameter_attr.name] = [[x] for x in parameter_attr.normal_values.split(",")]
else:
parameter_expect_dict[parameter_attr.name] = parameter_attr.normal_values.split(",")
else:
continue
if len(parameter_expect_dict[parameter_attr.name]) > expect_lenth:
expect_lenth = len(parameter_expect_dict[parameter_attr.name])
if parameter_attr.exception_values:
parameter_un_expect_dict[parameter_attr.name] = parameter_attr.exception_values.split(",")
else:
# raise Exception("接口参数%s无异常值请先确认接口参数。" % parameter_attr.name)
parameter_un_expect_dict[parameter_attr.name] = []
if len(parameter_un_expect_dict[parameter_attr.name]) > un_expect_lenth:
un_expect_lenth = len(parameter_un_expect_dict[parameter_attr.name])
return parameter_expect_dict, parameter_un_expect_dict, expect_lenth, un_expect_lenth
def generate_case_doc(self, interface_info, tags=None, demo=None):
if demo:
lenth, demo_json, paras_d = self.file.kw._clean_demo_to_less_key(demo)
doc_list = list()
doc_list.append(
" [Documentation] {} 接口路径:{}, {}".format(interface_info.interface_describe,
interface_info.type, interface_info.in_url))
# doc_list.append(self.doc_content_row_temp.format("输入参数名", "参数类型", "说明"))
# for parameters_info in parameters:
# sub_doc = self._generate_case_doc(parameters_info)
# doc_list.append(sub_doc)
if tags:
tag_list = tags.split(",")
tag = " [Tags]"
for tag_ in tag_list:
tag += " %s" % tag_
doc_list.append(tag)
if lenth > 1:
doc_list.append(
" # 请求参数说明 h:放header里的参数 u:放url路径节点中的参数 d:不放在url中在请求参数 p放在url问号后在key-value结构参数")
return "\n".join(doc_list)
def _generate_case_doc(self, request_parameter):
doc_content = list()
parameter_attr = SetAttr(request_parameter)
row = self.doc_content_row_temp.format(parameter_attr.name, parameter_attr.type, parameter_attr.note)
doc_content.append(row)
return "\n".join(doc_content)
def generate_case_file_path(self, interface_info):
path_cell_list = self._generate_case_file_path_info(interface_info.in_url)
path_cell_list.insert(0, self.file.case_dir)
return os.path.abspath(os.path.join(*path_cell_list[:-1]) + ".robot"), path_cell_list[-1]
def _generate_case_file_path_info(self, url):
head_list = []
para_list = []
host, url_last = re.search(r"(\S+\.cn|\S+\.com)(\S+)", url).groups()
path_first = re.search("//([\w+\-]+)\.", host).group(1)
head_list.append(path_first)
search = re.findall("[\w+\-_]+|[\{\w+\-_\}]+", url_last)
for item in search:
if "{" in item:
temp = item.replace("{", "").replace("}", "")
para_list.append(temp)
else:
head_list.append(item)
return head_list
def run_interface_case_generate(result_path, interface, demo_info, parameters, case_instance, tags=None, normal=None):
case_type_list = ["1001", "1101", "1102", "1201"]
not_exist_case_type = list()
exist_case_name = list()
case_path, _ = case_instance.generate_case_file_path(interface)
case_name_head = interface.name
if parameters:
for case_type in case_type_list:
case_name = "-".join([case_name_head, case_type])
if not case_instance.file.check_case_exist(case_path, case_name):
not_exist_case_type.append(case_type)
else:
exist_case_name.append(case_name)
else:
case_name = "-".join([case_name_head, "1001"])
if not case_instance.file.check_case_exist(case_path, case_name):
not_exist_case_type.append("1001")
else:
exist_case_name.append(case_name)
for item in exist_case_name:
msg = "接口url%s,%s,已存在用例%s,请确认!" % (interface.type, interface.in_url, item)
log.warning(msg)
case_instance.file.write_content_to_case_file(result_path, msg + "\n")
if not_exist_case_type:
if normal:
not_exist_case_type = ["1001"]
case_instance.file.generate_case_file(case_path)
try:
demo = json.loads(demo_info.request_demo)
except Exception as err:
log.error(traceback.print_exc())
log.warning("the demo of interface(%s) is empty,please check." % interface.id)
demo = dict()
try:
result = list()
result.append("")
result.append("-" * 60)
result.append("用例生成成功!")
for case_type in not_exist_case_type:
body = case_instance.create_case_content(result_path, interface, parameters, demo, case_type, tags=tags)
# result.append(body)
result.append(body.split("")[1])
log.info("\n".join(result))
except:
log.error("could not generate case for interface id: %s, url: %s" % (interface.id, interface.in_url))
log.error(traceback.print_exc())
else:
msg = "接口url%s,%s,已存在用例,请确认!" % (interface.type, interface.in_url)
log.warning(msg)
case_instance.file.write_content_to_case_file(result_path, msg + "\n")

View File

@@ -0,0 +1,833 @@
# -*- coding:utf-8 -*-
import copy
import importlib
import json
import os
import random
import re
import sys
import string
import time
import traceback
def get_project_root_path(path="base_framework"):
"""
获取项目目录
"""
o_path = os.getcwd()
try:
project_path = re.search(r"(.*%s)" % path, o_path).group(1)
return os.path.abspath(os.path.join(project_path, os.path.pardir))
except:
pass
Project_Path = get_project_root_path()
sys.path.append(Project_Path)
from base_framework.platform_tools.Keywords_service.keyword_service1 import SetAttr, log
def load_module_from_file(file_path, team):
module_file = re.search(r"(%s\\.*)\.py" % team, file_path)
if not module_file:
module_file = re.search(r"(%s.*)\.py" % team.lower(), file_path)
temp = module_file.group(1)
temp = temp.replace(os.sep, ".")
# try:
# module = importlib.import_module(temp)
# except Exception as err:
# temp = re.sub(r"%s\." % team, "%s." % team.lower(), temp)
# module = importlib.import_module(temp)
return importlib.import_module(temp)
class ITCaseFileOperation(object):
def __init__(self, team, kw_instance):
self.kw = kw_instance
self.all_url = kw_instance.all_url
self.kw_class_name = kw_instance.kw_class
self.case_dir = os.path.abspath(os.path.join(Project_Path, team, "test_case", "TestCase", "1.接口"))
self.env_path = os.path.abspath(
os.path.join(Project_Path, team, "test_case", "Resource", "AdapterKws", "env.robot"))
def _check_case_file_exist(self, file_path):
if os.path.exists(file_path) and os.path.isfile(file_path):
return True
else:
return False
def check_case_exist(self, case_path, case_name):
if self._check_case_file_exist(case_path):
with open(case_path, "r", encoding="utf-8") as f:
for line in f.readlines():
if line.startswith(case_name):
return True
else:
return False
else:
return False
def generate_case_file(self, file_path):
if not self._check_case_file_exist(file_path):
dirname = file_path[:-len(os.path.basename(file_path))]
if not os.path.exists(dirname):
os.makedirs(dirname)
self.write_content_to_case_file(file_path, self.generate_env_releate_path(dirname))
else:
with open(file_path, "r", encoding="utf-8") as f:
if f.readlines():
if "\n" != f.readlines()[-1]:
self.write_content_to_case_file(file_path, "\n")
def generate_env_releate_path(self, file_path):
return "*** Settings ***\nResource " + os.path.relpath(self.env_path,
file_path).replace("\\",
"/") + "\n\n*** Test Cases ***\n"
def _check_case_file_resource(self, file_path):
"""
确定case文件中是否有关键字
"""
with open(file_path, "a+", encoding="utf-8") as f:
content_list = f.readlines()
if "*** Keywords ***\n" not in content_list:
return True
else:
kw_index = content_list.rindex("*** Keywords ***\n")
for index in range(kw_index, len(content_list) + 1):
if "*** Test Cases ***\n" == content_list[index]:
status = True
if "*** Keywords ***\n" == content_list[index]:
status = False
return status
def write_content_to_case_file(self, file_path, content):
status = self._check_case_file_resource(file_path)
with open(file_path, "a+", encoding="utf-8") as f:
if status:
f.write(content)
else:
content = "*** Test Cases ***\n" + content
f.write(content)
class ITCaseContentOperation(object):
def __init__(self, team, kw_instance):
self.team = team
self.file = ITCaseFileOperation(team, kw_instance)
self.doc_content_row_temp = " ... | {} | {} | {} |"
self.normal_1001 = None
self.un_expect_list = None
self.case_string = None
def _generate_case_name(self, interface_name, case_type, case_des):
return "-".join([interface_name, case_type, case_des])
def _check_interface_confirm(self, interface_info):
if not interface_info.confirmed:
raise Exception("接口%s未确认,请先确认接口参数。" % interface_info.name)
def generate_case_body_all_1001_array(self, request_demo, parameters):
temp_list = list()
demo_copy = copy.deepcopy(request_demo)
for key, value in request_demo.items():
if not value:
demo_copy.pop(key)
if len(demo_copy.keys()) == 1:
demo_copy = demo_copy.pop(list(demo_copy.keys())[0])
dict_para, self.un_expect_list, _, _ = self._analysis_case_parameters_to_dict(parameters)
demo_add_values = self._analysis_case_parameters_to_value(demo_copy, dict_para)
data_list = self._analysis_dict_to_body_value(demo_copy, demo_add_values)
if isinstance(demo_copy, list):
for item in data_list:
temp_list.append([item])
data_list = temp_list
return data_list
def _generate_parameter_to_dict(self, parameters):
dict_temp = dict()
for parameter in parameters:
parameter_attr = SetAttr(parameter)
dict_temp[parameter_attr.name] = parameter_attr
return dict_temp
def _analysis_case_parameters_to_value_empty_dict(self, request_demo, parameters, type=None):
"""
循环生成缺少某个参数的值,其它正确的参数组合列表
"""
parameter_expect_list = list()
expect_lenth = 0
un_expect_lenth = 0
parameter_expect_dict = dict()
parameter_un_expect_dict = dict()
for key, parameter_attr in parameters.items():
if parameter_attr.normal_values:
parameter_expect_dict[parameter_attr.name] = parameter_attr.normal_values.split(",")
else:
parameter_expect_dict[parameter_attr.name] = [
self._generate_body_expect_type_value(parameter_attr.type)]
if len(parameter_expect_dict[parameter_attr.name]) > expect_lenth:
expect_lenth = len(parameter_expect_dict[parameter_attr.name])
if parameter_attr.exception_values:
parameter_un_expect_dict[parameter_attr.name] = parameter_attr.exception_values.split(",")
else:
parameter_un_expect_dict[parameter_attr.name] = [
self._generate_body_un_expect_type_value(parameter_attr.type)]
if len(parameter_un_expect_dict[parameter_attr.name]) > un_expect_lenth:
un_expect_lenth = len(parameter_un_expect_dict[parameter_attr.name])
for key in parameter_expect_dict.keys():
if key not in json.dumps(request_demo):
continue
value = copy.copy(parameter_expect_dict)
value[key] = ['NULL']
if parameters.get(key).is_need == 1:
status = "FAIL"
else:
status = "PASS"
if type == "1102":
name = "缺少参数%s" % key
else:
name = "缺少参数%s的值" % key
parameter_expect_list.append([value, status, name])
return parameter_expect_list
def _distinguish_parameters_by_is_needed(self, parameters):
"""
将必填参数和非必须参数分开成2个列表
"""
need_parameters = list()
no_need_parameters = list()
for parameter in parameters:
parameter_attr = SetAttr(parameter)
if parameter_attr.is_need != 0:
need_parameters.append(parameter_attr)
else:
no_need_parameters.append(parameter_attr)
return need_parameters, no_need_parameters
def _replace_null_value_no_need_parameters(self, demo, no_need_parameter_attrs):
"""
将所有非必填参数置空
"""
really_body = copy.deepcopy(demo)
for parameter_attr in no_need_parameter_attrs:
if re.search(r"\"%s\"" % parameter_attr.name, demo):
check_para = r"\"%s\":\s[\[\{]" % parameter_attr.name
if re.search(check_para, demo):
continue
try:
expect_value = parameter_attr.normal_values.split(",")[0]
except Exception as err:
log.error(err)
raise Exception("接口参数%s无正常值,请先确认接口参数。" % parameter_attr.name)
patten1 = r"\"%s\":\s\"%s\"" % (parameter_attr.name, expect_value)
replace1 = "\"%s\": \"NULL\"" % parameter_attr.name
really_body = re.sub(patten1, replace1, really_body)
return really_body
def generate_case_body_all_1101_array(self, request_demo, parameters):
"""
生成1101用例对应的所有请求参数组合
"""
body_array = list()
need, no_need = self._distinguish_parameters_by_is_needed(parameters)
demo_json = json.dumps(request_demo, ensure_ascii=False)
if no_need:
no_need_demo_json = self._replace_null_value_no_need_parameters(demo_json, no_need)
body_array.append([json.loads(no_need_demo_json), "PASS", "所有非必填参数为空"])
for item in need:
parameter_attr = copy.copy(item)
demo_json_copy = copy.copy(demo_json)
if re.search("\"%s\"" % parameter_attr.name, demo_json_copy):
check_para = r"\"%s\":\s\{|\"%s\":\s\[\{" % (parameter_attr.name, parameter_attr.name)
if re.search(check_para, demo_json_copy):
continue
name = "缺少参数%s" % parameter_attr.name
try:
expect_value = parameter_attr.normal_values.split(",")[0]
except Exception as err:
log.error(err)
raise Exception("接口参数%s无正常值,请先确认接口参数。" % parameter_attr.name)
if parameter_attr.type == "array":
patten1 = r"\"%s\":\s\[\"%s\"\]" % (parameter_attr.name, expect_value)
replace1 = "\"%s\": []" % parameter_attr.name
else:
patten1 = r"\"%s\":\s\"%s\"" % (parameter_attr.name, expect_value)
patten1 = patten1.replace("{", r"\{")
patten1 = patten1.replace("}", r"\}")
patten1 = patten1.replace("[", r"\[")
patten1 = patten1.replace("]", r"\]")
patten1 = patten1.replace("$", r"\$")
replace1 = "\"%s\": \"NULL\"" % parameter_attr.name
really_body = re.sub(patten1, replace1, demo_json_copy)
if parameter_attr.is_need == 1:
status = "FAIL"
else:
status = "PASS"
body_array.append([json.loads(really_body), status, name])
return body_array
def _clean_all_none_json_char(self, really_body):
"""
清除1102场景删除缺少参数后不规则的字符串内容
"""
really_body = re.sub(",\s,", ",", really_body)
really_body = re.sub("\[\s?,", "[", really_body)
really_body = re.sub("\{\s?,", "{", really_body)
really_body = re.sub(",\s\]", "]", really_body)
really_body = re.sub(",\s\}", "}", really_body)
really_body = re.sub("\s,", "", really_body)
return really_body
def _replace_null_all_no_need_parameters(self, demo, no_need_parameter_attrs):
"""
将所有非必填参数置空
"""
really_body = copy.deepcopy(demo)
for parameter_attr in no_need_parameter_attrs:
if re.search(r"\"%s\"" % parameter_attr.name, demo):
check_para = r"\"%s\":\s\{|\"%s\":\s\[\{" % (parameter_attr.name, parameter_attr.name)
if re.search(check_para, demo):
continue
try:
expect_value = parameter_attr.normal_values.split(",")[0]
except Exception as err:
log.error(err)
raise Exception("接口参数%s无正常值,请先确认接口参数。" % parameter_attr.name)
if parameter_attr.type == "array":
patten1 = r"\"%s\":\s\[\"%s\"\]" % (parameter_attr.name, expect_value)
else:
patten1 = r"\"%s\":\s\"%s\"" % (parameter_attr.name, expect_value)
replace1 = ""
really_body = re.sub(patten1, replace1, really_body)
really_body = self._clean_all_none_json_char(really_body)
return really_body
def generate_case_body_all_1102_array(self, request_demo, parameters):
"""
生成1102用例对应的所有参数组合
"""
body_array = list()
need, no_need = self._distinguish_parameters_by_is_needed(parameters)
demo_json = json.dumps(request_demo, ensure_ascii=False)
if no_need:
no_need_demo_json = self._replace_null_all_no_need_parameters(demo_json, no_need)
body_array.append([json.loads(no_need_demo_json), "PASS", "所有非必填参数均缺失"])
for item in need:
parameter_attr = copy.copy(item)
demo_json_copy = copy.copy(demo_json)
if re.search(r"\"%s\"" % parameter_attr.name, demo_json_copy):
check_para = r"\"%s\":\s\{|\"%s\":\s\[\{" % (parameter_attr.name, parameter_attr.name)
if re.search(check_para, demo_json_copy):
continue
name = "缺少参数%s" % parameter_attr.name
expect_value = parameter_attr.normal_values.split(",")[0]
if parameter_attr.type == "array":
patten1 = r"\"%s\":\s\[\"%s\"\]" % (parameter_attr.name, expect_value)
else:
patten1 = r"\"%s\":\s\"%s\"" % (parameter_attr.name, expect_value)
patten1 = patten1.replace("{", r"\{")
patten1 = patten1.replace("}", r"\}")
patten1 = patten1.replace("[", r"\[")
patten1 = patten1.replace("]", r"\]")
patten1 = patten1.replace("$", r"\$")
replace1 = ""
really_body = re.sub(patten1, replace1, demo_json_copy)
really_body = self._clean_all_none_json_char(really_body)
if parameter_attr.is_need == 1:
status = "FAIL"
else:
status = "PASS"
body_array.append([json.loads(really_body), status, name])
return body_array
def generate_case_body_all_1201_array(self, request_demo, parameters):
"""
生成1201用例对应的所有参数组合
"""
body_array = list()
demo_json = json.dumps(request_demo, ensure_ascii=False)
for item in parameters:
parameter_attr = SetAttr(item)
if re.search(r"\"%s\"" % parameter_attr.name, demo_json):
check_para = r"\"%s\":\s\{|\"%s\":\s\[\{" % (parameter_attr.name, parameter_attr.name)
if re.search(check_para, demo_json):
continue
for un_expect_item in self.un_expect_list.get(parameter_attr.name):
name = "参数%s使用异常值%s" % (parameter_attr.name, un_expect_item)
demo_json_copy = copy.copy(demo_json)
expect_value = parameter_attr.normal_values.split(",")[0]
if parameter_attr.type == "array":
patten1 = r"\"%s\":\s\[\"%s\"\]" % (parameter_attr.name, expect_value)
replace1 = '"%s": ["%s"]' % (parameter_attr.name, un_expect_item)
else:
patten1 = r"\"%s\":\s\"%s\"" % (parameter_attr.name, expect_value)
patten1 = patten1.replace("{", r"\{")
patten1 = patten1.replace("}", r"\}")
patten1 = patten1.replace("[", r"\[")
patten1 = patten1.replace("]", r"\]")
patten1 = patten1.replace("$", r"\$")
replace1 = '"%s": "%s"' % (parameter_attr.name, un_expect_item)
really_body = re.sub(patten1, replace1, demo_json_copy)
status = "FAIL"
body_array.append([json.loads(really_body), status, name])
return body_array
def create_case_content(self, result_path, interface_info, parameters, demo, case_type, tags=None):
"""
生成用例的所有内容
"""
self._check_interface_confirm(interface_info)
body_content = list()
doc = self.generate_case_doc(interface_info, tags=tags, demo=demo)
case_file, _ = self.generate_case_file_path(interface_info)
interface_name = interface_info.name
if not parameters:
body = self.generate_case_body_content(interface_info.in_url, doc, interface_name, case_type,
interface_info.interface_describe, None, status="PASS")
else:
try:
body_array = self.generate_case_body_all_1001_array(demo, parameters)
self.normal_1001 = body_array[0]
except TypeError:
log.warning(traceback.print_exc())
body_array = []
self.normal_1001 = {}
if case_type == "1001":
try:
body = self.generate_case_body_content(interface_info.in_url, doc, interface_name, case_type,
interface_info.interface_describe, body_array, status="PASS")
except Exception as err:
msg = "生成用例%s,%s失败原因如下:%s" % (interface_info.type, interface_info.in_url, traceback.print_exc())
log.error(msg)
self.file.write_content_to_case_file(result_path, msg + "\n")
elif case_type == "1101" or case_type == "1102" or case_type == "1201":
body_temp_list = []
# parameters_temp = self._generate_parameter_to_dict(parameters)
try:
body_array = eval(
"self.generate_case_body_all_%s_array(self.normal_1001, parameters)" % case_type)
if case_type == "1101":
name = "缺少参数值"
elif case_type == "1102":
name = "缺少参数key和值"
elif case_type == "1201":
name = "参数使用异常值"
else:
name = ""
body_tmp = self.generate_case_body_content(interface_info.in_url, doc, interface_name,
case_type,
name, body_array, status="PASS")
body_temp_list.append(body_tmp)
body = "".join(body_temp_list)
except Exception as err:
msg = "生成用例%s,%s失败原因如下:%s" % (interface_info.type, interface_info.in_url, traceback.print_exc())
log.error(msg)
self.file.write_content_to_case_file(result_path, msg + "\n")
raise err
body_content.append(body)
self.file.write_content_to_case_file(case_file, "\n".join(body_content))
msg = "接口url%s,%s,生成case%s成功!路径为:%s" % (interface_info.type, interface_info.in_url, case_type, case_file)
log.info(msg)
self.file.write_content_to_case_file(result_path, msg + "\n")
return msg
def generate_case_body_content(self, url, doc, interface_name, case_type, description, body_para, status="PASS"):
body_content = list()
case_name = self._generate_case_name(interface_name, case_type, description)
body_content.append(case_name)
body_content.append(doc)
# 如何需要自动生成1001类型用例的请求body数据请将304/305行放开并把306~310注释
request = self._generate_case_body_content(url, body_content=body_para, status=status)
body_content.append(request)
# if case_type != "1001":
# request = self._generate_case_body_content(url, body_content=body_para, status=status)
# body_content.append(request)
# else:
# body_content.append(" #请自行添加用例请求数据!\n")
return "\n".join(body_content)
def _generate_case_body_content(self, url, body_content=None, status="PASS"):
body_list = []
if body_content is None:
try:
body_request = " ${resp} %s" % (self.file.all_url.get(url)[1])
except Exception as err:
log.error(traceback.print_exc())
body_request = " #url: %s 无法找到对应的关键字,请检查并更新!" % url
body_list.append(body_request)
body_list.append(" Log ${resp}")
if self.team.upper() in ["TMO"]:
body_validate_success = " check_rf ${resp} %s" % '请自行添加检查结果'
else:
body_validate_code = " Should Be Equal ${resp['code']} ${200}"
body_validate_success = " Should Be True ${resp['success']}"
body_list.append(body_validate_code)
body_list.append(body_validate_success)
else:
if not body_content:
body_create = " #request_demo无内容或者parameters在数据表中不全请先检查再生成 \n ${body} Evaluate %s" % body_content
body_list.append(body_create)
count = 0
for real_body in body_content:
result = {"message": "", "code": 200, "success": True}
temp = copy.copy(real_body)
if len(real_body) == 3 and isinstance(real_body, list):
if real_body[1] == "PASS" or real_body[1] == "FAIL":
real_body = temp[0]
status = temp[1]
case_description = temp[2]
body_list.append(" #%s" % case_description)
try:
module = load_module_from_file(self.file.kw.kw_file_path, self.team)
importlib.reload(module)
if isinstance(real_body, list):
temp_type = "*"
else:
temp_type = "**"
result = eval(
"%s.%s().%s(%sreal_body)" % (
"module", self.file.kw_class_name, self.file.all_url.get(url)[1], temp_type))
except:
msg = "#url: %s 无法通过参数得到请求结果!" % url
log.warning(real_body)
log.warning(msg)
log.warning(traceback.print_exc())
if "${time}" in str(real_body):
body_list.append(" ${time} get time epoch")
body_create = " ${body_%s} Evaluate %s" % (count, real_body)
try:
if isinstance(real_body, list):
body_request = " ${resp_%s} %s %s" % (
count, self.file.all_url.get(url)[1], "@{body_%s}" % count)
elif isinstance(real_body, dict):
body_request = " ${resp_%s} %s %s" % (
count, self.file.all_url.get(url)[1], "&{body_%s}" % count)
except Exception as err:
log.error(traceback.print_exc())
body_request = " #url: %s 无法找到对应的关键字,请检查并更新!" % url
body_list.append(body_create)
body_list.append(body_request)
body_list.append(" Log ${resp_%s}" % count)
if self.team.upper() in ["TMO"]:
body_validate_resp = " check_rf ${resp_%s} %s" % (count, result)
else:
body_validate_code = " Should Be Equal as strings ${resp_%s['code']} ${%s}"
# body_validate_success = " %s ${resp_%s['success']}"
body_validate_success = " %s ${resp_%s['success']} %s"
body_validate_resp = " %s ${resp_%s[\"message\"]} %s"
if isinstance(result, str):
body_validate_code = " #特殊接口返回!"
body_validate_success = " #返回为bytes类型的字符码。仅检查结果是否相等"
body_validate_resp = " Should Be Equal as strings ${resp_%s} %s" % (count, result)
elif status == "PASS":
body_validate_code = body_validate_code % (count, result['code'])
body_validate_success = body_validate_success % ("Should Be True", count, "")
try:
if result["message"]:
body_validate_resp = body_validate_resp % (
"Should Be Equal as strings", count, result["message"])
else:
body_validate_resp = body_validate_resp % (
"Should Be Equal as strings", count, '${EMPTY}')
except KeyError as err:
body_validate_resp = " #resp中没有message请后续自行添加"
log.warning(err)
log.warning("resp中没有message请后续自行添加")
else:
try:
body_validate_code = body_validate_code % (count, result['code'])
except Exception as e:
if "status" in result:
body_validate_code = body_validate_code % (count, result['status'])
body_validate_code = body_validate_code.replace("code", "status")
else:
raise KeyError("接口不中无code返回请与开发确认")
try:
body_validate_success = body_validate_success % (
"Should Be Equal As Strings", count, result["success"])
except Exception as err:
if "error" in result:
body_validate_success = body_validate_success % (
"Should Be Equal As Strings", count, result["error"])
body_validate_success = body_validate_success.replace("success", "error")
else:
raise KeyError("接口不中无success返回请与开发确认")
try:
if result.get("message"):
if re.search("[a-zA-Z0-9]{32}", result.get("message", "")):
body_validate_resp = body_validate_resp % ("should contain", count,
re.sub("[a-zA-Z0-9]{32}", "", result["message"]))
else:
body_validate_resp = body_validate_resp % (
"should be equal as strings", count, result["message"])
else:
body_validate_resp = body_validate_resp % (
"Should Be Equal as strings", count, '${EMPTY}')
except KeyError as err:
body_validate_resp = " #resp中没有message请后续自行添加"
log.warning(err)
log.warning("resp中没有message请后续自行添加")
body_list.append(body_validate_code)
body_list.append(body_validate_success)
body_list.append(body_validate_resp)
# body_list.append(" #请自行添加data校验")
count += 1
body_list.append("\n")
return "\n".join(body_list)
def _generate_body_expect_type_value(self, type):
if type.lower() == 'integer':
value = random.randint(0, 100)
elif type.lower() == "string":
value = "".join([random.choice(string.digits + string.ascii_letters) for i in range(5)])
elif type.lower() == "date":
value = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
elif type.lower() == "boolean":
value = True
elif type.lower() == "array":
value = [1]
else:
value = "123"
return value
def _generate_body_un_expect_type_value(self, type):
value = ""
if type.lower() == 'integer':
value = "".join([random.choice(string.digits + string.ascii_letters) for i in range(5)])
elif type.lower() == "string":
value = random.randint(0, 10000)
else:
value = False
return value
def _analysis_dict_to_body_value(self, dict_none, dict_data):
"""
生成所有请求参数的组合列表
"""
data_list = []
if isinstance(dict_none, list):
if dict_none:
for index in range(len(dict_none)):
data = self._analysis_dict_to_body_value(dict_none[index], dict_data[index])
data_list.extend(data)
else:
data_list = dict_data
elif isinstance(dict_none, dict):
try:
len_num = self._get_nums(dict_data)
except Exception as e:
# log.error(e)
log.error("数据表request_parameters中参数不全请使用interface_hunter补全参数")
raise e
for i in range(0, len_num):
copy_dict = copy.copy(dict_none)
for key, value in copy_dict.items():
data = self._analysis_dict_to_body_value(copy_dict[key], dict_data[key])
if not data:
copy_dict[key] = None
elif i >= len(data):
copy_dict[key] = data[0]
if isinstance(value, list):
copy_dict[key] = [data[0]]
else:
copy_dict[key] = data[i]
if isinstance(value, list):
copy_dict[key] = [data[i]]
data_list.append(copy_dict)
else:
data_list = dict_data
return data_list
def _get_nums(self, dict_data):
"""
获取所有参数对应值的最大长度
"""
nums_list = [0]
if isinstance(dict_data, list):
for item in dict_data:
if isinstance(item, dict):
data = self._get_nums(dict_data[0])
nums_list.append(data)
else:
nums_list.append(len(dict_data))
elif isinstance(dict_data, dict):
for value in dict_data.values():
data = self._get_nums(value)
nums_list.append(data)
elif dict_data == None:
nums_list.append(0)
else:
nums_list.append(len(dict_data))
return max(nums_list)
def _analysis_case_parameters_to_value(self, interface_demo, parameters):
"""
根据demo将每个参数的对应值的列表写回demo
"""
body = copy.copy(interface_demo)
if isinstance(body, list):
for index in range(len(body)):
item = body[index]
body[index] = self._analysis_case_parameters_to_value(item, parameters)
elif isinstance(body, dict):
for key, value in body.items():
if isinstance(value, dict) or isinstance(value, list):
if value:
body[key] = self._analysis_case_parameters_to_value(body.get(key), parameters)
else:
body[key] = parameters.get(key)
else:
body[key] = parameters.get(key)
return body
def _analysis_case_parameters_to_dict(self, parameters):
"""
根据所有参数生成正常值 和异常值的列表
"""
expect_lenth = 0
un_expect_lenth = 0
parameter_expect_dict = dict()
parameter_un_expect_dict = dict()
for parameter in parameters:
parameter_attr = SetAttr(parameter)
if parameter_attr.normal_values:
if parameter_attr.normal_values.startswith("["):
parameter_expect_dict[parameter_attr.name] = parameter_attr.normal_values.split(",")
else:
if parameter_attr.type == "array":
parameter_expect_dict[parameter_attr.name] = [[x] for x in parameter_attr.normal_values.split(",")]
else:
parameter_expect_dict[parameter_attr.name] = parameter_attr.normal_values.split(",")
else:
continue
if len(parameter_expect_dict[parameter_attr.name]) > expect_lenth:
expect_lenth = len(parameter_expect_dict[parameter_attr.name])
if parameter_attr.exception_values:
parameter_un_expect_dict[parameter_attr.name] = parameter_attr.exception_values.split(",")
else:
# raise Exception("接口参数%s无异常值请先确认接口参数。" % parameter_attr.name)
parameter_un_expect_dict[parameter_attr.name] = []
if len(parameter_un_expect_dict[parameter_attr.name]) > un_expect_lenth:
un_expect_lenth = len(parameter_un_expect_dict[parameter_attr.name])
return parameter_expect_dict, parameter_un_expect_dict, expect_lenth, un_expect_lenth
def generate_case_doc(self, interface_info, tags=None, demo=None):
if demo:
lenth, demo_json, paras_d = self.file.kw._clean_demo_to_less_key(demo)
doc_list = list()
doc_list.append(
" [Documentation] {} 接口路径:{}, {}".format(interface_info.interface_describe,
interface_info.type, interface_info.in_url))
# doc_list.append(self.doc_content_row_temp.format("输入参数名", "参数类型", "说明"))
# for parameters_info in parameters:
# sub_doc = self._generate_case_doc(parameters_info)
# doc_list.append(sub_doc)
if tags:
tag_list = tags.split(",")
tag = " [Tags]"
for tag_ in tag_list:
tag += " %s" % tag_
doc_list.append(tag)
if lenth > 1:
doc_list.append(
" # 请求参数说明 h:放header里的参数 u:放url路径节点中的参数 d:不放在url中在请求参数 p放在url问号后在key-value结构参数")
return "\n".join(doc_list)
def _generate_case_doc(self, request_parameter):
doc_content = list()
parameter_attr = SetAttr(request_parameter)
row = self.doc_content_row_temp.format(parameter_attr.name, parameter_attr.type, parameter_attr.note)
doc_content.append(row)
return "\n".join(doc_content)
def generate_case_file_path(self, interface_info):
path_cell_list = self._generate_case_file_path_info(interface_info.in_url)
path_cell_list.insert(0, self.file.case_dir)
return os.path.abspath(os.path.join(*path_cell_list[:-1]) + ".robot"), path_cell_list[-1]
def _generate_case_file_path_info(self, url):
head_list = []
para_list = []
host, url_last = re.search(r"(\S+\.cn|\S+\.com)(\S+)", url).groups()
path_first = re.search("//([\w+\-]+)\.", host).group(1)
head_list.append(path_first)
search = re.findall("[\w+\-_]+|[\{\w+\-_\}]+", url_last)
for item in search:
if "{" in item:
temp = item.replace("{", "").replace("}", "")
para_list.append(temp)
else:
head_list.append(item)
return head_list
def run_interface_case_generate(result_path, interface, demo_info, parameters, case_instance, tags=None, normal=None):
case_type_list = ["1001", "1101", "1102", "1201"]
not_exist_case_type = list()
exist_case_name = list()
case_path, _ = case_instance.generate_case_file_path(interface)
case_name_head = interface.name
if parameters:
for case_type in case_type_list:
case_name = "-".join([case_name_head, case_type])
if not case_instance.file.check_case_exist(case_path, case_name):
not_exist_case_type.append(case_type)
else:
exist_case_name.append(case_name)
else:
case_name = "-".join([case_name_head, "1001"])
if not case_instance.file.check_case_exist(case_path, case_name):
not_exist_case_type.append("1001")
else:
exist_case_name.append(case_name)
for item in exist_case_name:
msg = "接口url%s,%s,已存在用例%s,请确认!" % (interface.type, interface.in_url, item)
log.warning(msg)
case_instance.file.write_content_to_case_file(result_path, msg + "\n")
if not_exist_case_type:
if normal:
not_exist_case_type = ["1001"]
case_instance.file.generate_case_file(case_path)
try:
demo = json.loads(demo_info.request_demo)
except Exception as err:
log.error(traceback.print_exc())
log.warning("the demo of interface(%s) is empty,please check." % interface.id)
demo = dict()
try:
result = list()
result.append("")
result.append("-" * 60)
result.append("用例生成成功!")
for case_type in not_exist_case_type:
body = case_instance.create_case_content(result_path, interface, parameters, demo, case_type, tags=tags)
# result.append(body)
result.append(body.split("")[1])
log.info("\n".join(result))
except:
log.error("could not generate case for interface id: %s, url: %s" % (interface.id, interface.in_url))
log.error(traceback.print_exc())
else:
msg = "接口url%s,%s,已存在用例,请确认!" % (interface.type, interface.in_url)
log.warning(msg)
case_instance.file.write_content_to_case_file(result_path, msg + "\n")

View File

@@ -0,0 +1,3 @@
目录结构说明:
使用者:王刚
用途存放自动生成RF层用例的脚本