from typing import List from apps.dict.models import DictItem from apps.project.models import TestDemand from html.parser import HTMLParser from django.db.models import QuerySet # 导入生成文档检查器log - 单例模式 from apps.createSeiTaiDocument.extensions.logger import GenerateLogger logger = GenerateLogger(model='字典模块') # 传入一个字符串数字以及字典标志code,返回真实的title名字 def get_str_dict(a, dict_code): dict_obj = DictItem.objects.filter(dict__code=dict_code, key=a).first() if dict_obj: return dict_obj.title else: # 如果用户没填写内容则记录检查中心log logger.write_warning_log(fragment='字典数据缺失', message=f'字典数据{dict_code}数据缺失,请检查相应数据是否存在') return '' # 传入一个字符串数字以及字典标志code,返回字典所属的缩写(show_title) def get_str_abbr(a, dict_code): dict_obj = DictItem.objects.filter(dict__code=dict_code, key=a).first() if dict_obj: return dict_obj.show_title else: logger.write_warning_log(fragment='字典数据缺失', message=f'查询字段数据缩写问题,字典数据{dict_code}数据可能缺失') return "" # 传入一个字符串数组(测试项类型),字典标志code,返回(真实title,sort) def get_str_dict_plus(a, dict_code): dict_obj = DictItem.objects.filter(dict__code=dict_code, key=a).first() if dict_obj: return dict_obj.title, dict_obj.sort else: logger.write_warning_log(fragment='字典数据查询错误', message=f'字典{dict_code}未查询到数据,请检查') return "", 1 # 找到testType字典中的缩写,例如“DC”“FT” def get_testType(a, dict_code): dict_obj = DictItem.objects.filter(dict__code=dict_code, key=a).first() if dict_obj: return dict_obj.show_title else: logger.write_warning_log(fragment='字典数据查询错误', message=f'查询字段数据缩写问题,字典数据{dict_code}数据可能缺失') return "" # 标识处理:获取测试需求(测试项的)生成文档的ident(标识) def get_ident(test_item): # key_index = int(test_item.key.split("-")[-1]) + 1 # test_index = str(key_index).rjust(3, '0') reveal_ident = "_".join( ["XQ", get_testType(test_item.testType, "testType"), test_item.ident]) return reveal_ident # 标识处理:传入demand的ident以及case,返回case的ident def get_case_ident(demand_ident, case): key_index = int(case.key.split("-")[-1]) + 1 test_index = str(key_index).rjust(3, '0') reveal_ident = "_".join([demand_ident.replace("XQ", "YL"), test_index]) return reveal_ident # 传入字典code,以及字符串数组返回一个数组,每个数组是dict def get_list_dict(dict_code: str, str_list: List[str]): result = [] qss = DictItem.objects.filter(dict__code=dict_code) for st in str_list: res = {} for qs in qss: if st == qs.key: res['ident_version'] = qs.title res['doc_name'] = qs.doc_name res['publish_date'] = qs.publish_date res['source'] = qs.source result.append(res) return result # 传入字典code,以及字符串数组返回一个列表,每个元素是dict,包含字典item很多信息 def get_list_dict_info(dict_code, str_list): """传入字典的字符串列表,输出每个元素为dict的列表信息""" result = [] qss = DictItem.objects.filter(dict__code=dict_code) # type:ignore for st in str_list: res = {} for qs in qss: if st == qs.key: res['title'] = qs.title res['index'] = qs.sort result.append(res) return result # 传入字典code,以及单个字典字符串,输出一个dict带信息 def get_dict_info(dict_code, item_str): """传入字典的字符串单个表示,输出dict包含排序index字段""" qss = DictItem.objects.filter(dict__code=dict_code) res = {} for qs in qss: if item_str == qs.key: res['title'] = qs.title res['index'] = qs.sort return res # 简单HTML解析器 - 解析富文本的parser - 复杂的使用apps/createDocument/extensions/parse_rich_text.py class MyHTMLParser(HTMLParser): def __init__(self): HTMLParser.__init__(self) self.allStrList = [] def error(self, message): print("HTML解析器出错,error信息为:", message) def handle_starttag(self, tag, attrs): if tag == 'img': img_base64 = attrs[0][1] self.allStrList.append(img_base64) def handle_endtag(self, tag): pass def handle_data(self, data): if data != '\n': self.allStrList.append(data) # 不提取图片的HTML解析器 class MyHTMLParser_p(HTMLParser): def __init__(self): HTMLParser.__init__(self) self.allStrList = [] def handle_data(self, data): if data != '\n': self.allStrList.append(data) def create_problem_grade_str(problems): """传入问题qs,生成到文档的字符串:严重问题4个、一般问题10个""" problem_r1_grade_dict = {} for problem in problems: grade_key: str = get_str_dict(problem.grade, 'problemGrade') if grade_key in problem_r1_grade_dict.keys(): problem_r1_grade_dict[grade_key] += 1 else: problem_r1_grade_dict[grade_key] = 1 problem_r1_grade_list = [] for key, value in problem_r1_grade_dict.items(): problem_r1_grade_list.append("".join([f"{key}问题", f"{value}个"])) return "、".join(problem_r1_grade_list) def create_problem_type_str(problems): """传入问题qs,生成到文档的字符串:文档问题1个,程序问题10个""" problem_r1_type_dict = {} for problem in problems: type_key: str = get_str_dict(problem.type, 'problemType') if type_key in problem_r1_type_dict.keys(): problem_r1_type_dict[type_key] += 1 else: problem_r1_type_dict[type_key] = 1 problem_r1_type_list = [] for key, value in problem_r1_type_dict.items(): problem_r1_type_list.append("".join([f"{key}", f"{value}个"])) return "、".join(problem_r1_type_list) def create_str_testType_list(cases): """传入用例的qs,生成其测试类型的字符串:例如包含xxx测试5个,xxx测试11个,返回的是元组第二个元素表示测试类型个数""" test_type_set: set = set() for case in cases: demand: TestDemand = case.test test_type_set.add(demand.testType) test_type_list = get_list_dict_info('testType', list(test_type_set)) test_type_list.sort(key=lambda x: int(x['index'])) round1_testType_list = list(map(lambda x: x['title'], test_type_list)) return round1_testType_list, len(test_type_list) def util_func(item): """辅助函数,将下面函数返回的summary_list改造为以需求类型执行统计列表""" transform_item = {'title': item['title'], 'total_count': 0, 'exe_count': 0, 'not_exe_count': 0, 'pass_count': 0, 'not_pass_count': 0} for it in item['demand_list']: transform_item['total_count'] += it['total_count'] transform_item['exe_count'] += it['exe_count'] transform_item['not_exe_count'] += it['not_exe_count'] transform_item['pass_count'] += it['pass_count'] transform_item['not_pass_count'] += it['not_pass_count'] return transform_item def create_demand_summary(demands: QuerySet, project_ident: str): """ [ { 'title':'功能测试_5', 'demand_list':[ { 'name': '测试项1', 'total_count': 1, 'exe_count': 1, 'not_exe_count': 0, 'pass_count': 1, 'not_pass_count': 0, 'conclusion': '通过', 'problems': '/' } ] }, ] """ summary_dict = {} # 后面再变为数组 # 1.首先根据testType字段生成一个一个dict for demand in demands: # 取出testType -> '4'(后面查字典) test_type_num = demand.testType # 查出需求类型的sort与testType真实名字,组合为一个字符串作为key testTypeStr, testTypeSort = get_str_dict_plus(test_type_num, 'testType') testType_info = testTypeStr + '_' + str(testTypeSort) demand_dict = { 'name': demand.name, 'total_count': 0, 'exe_count': 0, 'not_exe_count': 0, 'pass_count': 0, 'not_pass_count': 0, 'conclusion': '通过', 'problems': "/" } # 查询当前测试需求下用例 demand_problem_list = set() for case in demand.tcField.all(): demand_dict['total_count'] += 1 # 要遍历下面的测试步骤 isPassed = True isExe = True for step in case.step.all(): # 所有步骤有一个未通过则是未通过,所有都执行则是已执行 if step.passed == '2': isPassed = False isExe = True break if step.passed == '3': isExe = False if isPassed: demand_dict['pass_count'] += 1 else: demand_dict['not_pass_count'] += 1 demand_dict['conclusion'] = '未通过' if isExe: demand_dict['exe_count'] += 1 else: demand_dict['not_exe_count'] += 1 # 查询每个用例下面的问题单,将问题单的ident弄出来 for problem in case.caseField.all(): problem_ident = 'PT_' + project_ident + '_' + problem.ident.rjust(3, '0') demand_problem_list.add(problem_ident) if len(list(demand_problem_list)) > 0: demand_dict['problems'] = "\a".join(list(demand_problem_list)) if testType_info in summary_dict.keys(): summary_dict[testType_info].append(demand_dict) else: summary_dict[testType_info] = [demand_dict] summary_list = [] for key, value in summary_dict.items(): one_dict = { 'title': key, 'demand_list': value } summary_list.append(one_dict) # 根据其排序 summary_list.sort(key=lambda x: int(x['title'].split('_')[-1])) # 然后将_5这种替换掉 for one in summary_list: one['title'] = one['title'].split("_")[0] # ~~~~还需要返回一个 -> 测试类型的用例执行情况 demandType_exe_list = list(map(util_func, summary_list)) return summary_list, demandType_exe_list def create_problem_table(problems): """传入问题单qs,输出按问题种类分的问题统计表的数据""" res_list = [{ 'name': '一般问题', 'xq_count': 0, 'sj_count': 0, 'wd_count': 0, 'bm_count': 0, 'data_count': 0, 'other_count': 0, 'closed_count': 0, 'non_closed_count': 0, }, { 'name': '严重问题', 'xq_count': 0, 'sj_count': 0, 'wd_count': 0, 'bm_count': 0, 'data_count': 0, 'other_count': 0, 'closed_count': 0, 'non_closed_count': 0, }, { 'name': '建议', 'xq_count': 0, 'sj_count': 0, 'wd_count': 0, 'bm_count': 0, 'data_count': 0, 'other_count': 0, 'closed_count': 0, 'non_closed_count': 0, }, { 'name': '重大问题', 'xq_count': 0, 'sj_count': 0, 'wd_count': 0, 'bm_count': 0, 'data_count': 0, 'other_count': 0, 'closed_count': 0, 'non_closed_count': 0, }] for problem in problems: index = int(problem.grade) - 1 if problem.type == '1': res_list[index]['other_count'] += 1 elif problem.type == '2': res_list[index]['wd_count'] += 1 elif problem.type == '3': res_list[index]['bm_count'] += 1 elif problem.type == '4': res_list[index]['sj_count'] += 1 elif problem.type == '5': res_list[index]['xq_count'] += 1 elif problem.type == '6': res_list[index]['data_count'] += 1 # 是否归零 if problem.status == '1': res_list[index]['closed_count'] += 1 else: res_list[index]['non_closed_count'] += 1 return res_list def create_problem_type_table(problems): """传入问题qs,解析出按测试类型分的问题统计表格""" res_list = [{ 'name': '一般问题', 'wd_count': 0, 'jt_count': 0, 'dm_count': 0, 'dt_count': 0, 'data_count': 0, 'closed_count': 0, 'non_closed_count': 0, }, { 'name': '严重问题', 'wd_count': 0, 'jt_count': 0, 'dm_count': 0, 'dt_count': 0, 'data_count': 0, 'closed_count': 0, 'non_closed_count': 0, }, { 'name': '建议', 'wd_count': 0, 'jt_count': 0, 'dm_count': 0, 'dt_count': 0, 'data_count': 0, 'closed_count': 0, 'non_closed_count': 0, }, { 'name': '重大问题', 'wd_count': 0, 'jt_count': 0, 'dm_count': 0, 'dt_count': 0, 'data_count': 0, 'closed_count': 0, 'non_closed_count': 0, }] for problem in problems: index = int(problem.grade) - 1 belong_demand: TestDemand = problem.case.all()[0].test if belong_demand.testType == '8': # 属于文档审查问题 res_list[index]['wd_count'] += 1 elif belong_demand.testType == '15': # 属于静态分析问题 res_list[index]['jt_count'] += 1 elif belong_demand.testType == '2' or belong_demand.testType == '3': # 属于代码审查和走查 res_list[index]['dm_count'] += 1 else: # 属于动态发现问题 res_list[index]['dt_count'] += 1 # 是否归零 if problem.status == '1': res_list[index]['closed_count'] += 1 else: res_list[index]['non_closed_count'] += 1 return res_list def get_demand_testTypes(demand_qs) -> str: """传入测试项qs,返回字符串类似于“静态分析、代码审查、功能测试等”""" testType_list = list(demand_qs.values("testType").distinct().order_by('testType')) t_code_list = [item['testType'] for item in testType_list] t_code_list = get_list_dict_info('testType', t_code_list) t_code_list.sort(key=lambda x: int(x['index'])) t_str = [item['title'] for item in t_code_list] return '、'.join(t_str) if len(t_str) > 0 else "测试"