实现AI生成测试项接口

This commit is contained in:
2026-05-29 16:20:30 +08:00
parent 56aed87497
commit 6f865cc7b5
11 changed files with 368 additions and 378 deletions

View File

@@ -3,12 +3,12 @@ from pathlib import Path
from ninja_extra import api_controller, ControllerBase, route
from django.db import transaction
from django.shortcuts import get_object_or_404
from django.db.models import Q, QuerySet
from django.db.models import Q
from docxtpl import DocxTemplate
from typing import Optional
from docx import Document
from ninja_extra.permissions import IsAuthenticated
from ninja_jwt.authentication import JWTAuth
from ninja_extra.permissions import IsAuthenticated # type:ignore
from ninja_jwt.authentication import JWTAuth # type:ignore
# 导入模型
from apps.project.models import Project, Dut, TestDemand, Problem
# 工具类函数
@@ -143,18 +143,18 @@ class GenerateControllerBG(ControllerBase):
# 找到第一轮轮次对象、第二轮轮次对象
round1 = project_obj.pField.filter(key='0').first()
# 第一轮测试项个数
round1_demand_qs = round1.rtField.all()
round1_demand_qs = round1 and round1.rtField.all()
# 第一轮用例个数
round1_case_qs = round1.rcField.all()
round1_case_qs = round1.rcField.all() # type:ignore
# 这部分找出第一轮的所有测试类型,输出字符串,并排序
test_type_set: set = set()
for case in round1_case_qs:
for case in round1_case_qs: # type:ignore
demand: TestDemand = case.test
test_type_set.add(demand.testType)
round1_testType_list = list(
map(lambda x: x['ident_version'], get_list_dict('testType', list(test_type_set))))
# 这里找出第一轮,源代码被测件,并获取版本
so_dut = round1.rdField.filter(type='SO').first()
so_dut = round1.rdField.filter(type='SO').first() # type:ignore
so_dut_verson = "$请添加第一轮的源代码信息$"
if so_dut:
so_dut_verson = so_dut.version
@@ -193,7 +193,7 @@ class GenerateControllerBG(ControllerBase):
'start_time_year': project_obj.beginTime.year,
'start_time_month': project_obj.beginTime.month,
'round1_case_count': round1_case_qs.count(),
'round1_demand_count': round1_demand_qs.count(),
'round1_demand_count': round1_demand_qs.count(), # type:ignore
'round1_testType_str': ''.join(round1_testType_list),
'testType_count': len(round1_testType_list),
'round1_version': so_dut_verson,
@@ -290,26 +290,26 @@ class GenerateControllerBG(ControllerBase):
problems_doc_r1 = problems_r1.filter(case__test__testType='8') # 第一轮所有文档问题
# 3.第一轮代码审查问题统计/版本
source_r1_dut = round1.rdField.filter(type='SO').first() # !warning:小变量-第一轮源代码对象
source_r1_dut = round1.rdField.filter(type='SO').first() # type:ignore
program_r1_problems = problems_r1.filter(case__test__testType='2')
# 4.第一轮代码走查问题统计/版本
zou_r1_problems = problems_r1.filter(case__test__testType='3')
# 找下是否存在代码走查测试项
r1_demand_qs = round1.rtField.filter(testType='3')
r1_demand_qs = round1.rtField.filter(testType='3') # type:ignore
has_zou = True if r1_demand_qs.count() > 0 else False
# 5.第一轮静态分析问题统计
static_problems = problems_r1.filter(case__test__testType='15')
# 6.第一轮动态测试用例个数(动态测试-非静态分析、文档审查、代码审查、代码走查4个)
case_r1_qs = round1.rcField.filter(~Q(test__testType='2'), ~Q(test__testType='3'),
case_r1_qs = round1.rcField.filter(~Q(test__testType='2'), ~Q(test__testType='3'), # type:ignore
~Q(test__testType='8'),
~Q(test__testType='15'),
round__key='0') # !warning:中变量-第一轮动态测试用例qs
testType_list, testType_count = create_str_testType_list(case_r1_qs)
## 动态测试(第一轮)各个类型测试用例执行表/各个测试需求表
demand_r1_dynamic_qs = round1.rtField.filter(~Q(testType='2'), ~Q(testType='3'), ~Q(testType='8'),
demand_r1_dynamic_qs = round1.rtField.filter(~Q(testType='2'), ~Q(testType='3'), ~Q(testType='8'), # type:ignore
~Q(testType='15')) # !warning:中变量:第一轮动态测试的测试项
summary_r1_demand_info, summry_r1_demandType_info = create_demand_summary(demand_r1_dynamic_qs,
project_ident)
@@ -678,14 +678,14 @@ class GenerateControllerBG(ControllerBase):
case__test__testType__in=['2', '3', '8', '15']).distinct()
for problem in r1_static_problems:
problem_dict = create_one_problem_dit(problem, problem_prefix, doc)
round_dict['static'].append(problem_dict)
round_dict['static'].append(problem_dict) # type:ignore
# 找出轮次中动态问题
r1_dynamic_problems = problems.filter(case__round__key=round_str).exclude(
case__test__testType__in=['2', '3', '8', '15']).distinct()
for problem in r1_dynamic_problems:
problem_dict = create_one_problem_dit(problem, problem_prefix, doc)
round_dict['dynamic'].append(problem_dict)
round_dict['dynamic'].append(problem_dict) # type:ignore
data_list.append(round_dict)
context = {

View File

@@ -55,7 +55,7 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
# 查出第一轮所有testdemand
project_round_one = project_qs.pField.filter(key=0).first()
testDemand_qs = project_round_one.rtField.all().select_related('design')
testDemand_qs = project_round_one.rtField.all().select_related('design') # type:ignore
# 按照自己key排序这样可以按照design的key排序
sorted_demand_qs = sorted(testDemand_qs, key=demand_sort_by_designKey)
@@ -228,9 +228,9 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
# 2025/12/11将20250417格式改为2025年04月17日 - 封装函数,传入字典和键值,修改对应键值信息
def change_time_to_another(self, context: dict, key_list: list[str]):
for key in key_list:
time_val = context.get(key, None)
time_val = context.get(key)
if time_val:
context[key] = datetime.strptime(time_val, "%Y%m%d").strftime("%Y年%m月%d")
context[key] = datetime.strptime(time_val, "%Y%m%d").strftime("%Y年%m月%d") # type:ignore
return context
# 生成【主要功能和性能指标】文档片段
@@ -361,7 +361,7 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
if qs.exists():
data_qs = qs.first().data_schemas
context = cls.create_data_schema_list_context(data_qs, doc)
doc.render(context)
doc.render(context or {})
try:
doc.save(Path.cwd() / "media" / project_path(id) / "output_dir" / r_filename)
return ChenResponse(status=200, code=200, message="文档生成成功!")
@@ -430,9 +430,9 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
image_render = None
fontnote = None
if image_obj.exists():
base64_bytes = base64.b64decode(image_obj.first().content.replace("data:image/png;base64,", ""))
base64_bytes = base64.b64decode(image_obj.first().content.replace("data:image/png;base64,", "")) # type:ignore
image_render = InlineImage(doc, io.BytesIO(base64_bytes), width=Mm(120))
fontnote = image_obj.first().fontnote
fontnote = image_obj.first().fontnote # type:ignore
context = {
'project_name': project_name,
'iters': interfaceNameList,
@@ -604,12 +604,12 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
qs = EnvAnalysis.objects.filter(project=project_obj)
if qs.exists():
obj = qs.first()
table_data = obj.table
table_data = obj.table # type:ignore
subdoc = create_table_context(table_data, doc)
context = {
"description": obj.description,
"description": obj.description, # type:ignore
"table": subdoc,
"fontnote": obj.fontnote,
"fontnote": obj.fontnote, # type:ignore
}
doc.render(context, autoescape=True)
try:
@@ -643,7 +643,7 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
devplant_list = [item['ident_version'] for item in devplants]
# 版本先找第一轮
project_round = project_qs.pField.filter(key=0).first()
first_round_SO = project_round.rdField.filter(type='SO').first()
first_round_SO = project_round.rdField.filter(type='SO').first() # type:ignore
if not first_round_SO:
return ChenResponse(code=400, status=400, message='您还未创建轮次,请进入工作区创建')
version = first_round_SO.version
@@ -721,7 +721,7 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
isDmsc = True if int(security) <= 2 else False
# 获取第一轮所有测试项QuerySet
project_round_one = project_qs.pField.filter(key=0).first()
testDemand_qs = project_round_one.rtField.all()
testDemand_qs = project_round_one.rtField.all() # type:ignore
# grouped_data的键是测试类型名称值为测试项名称数组
grouped_data = {}
for item in testDemand_qs:
@@ -819,9 +819,9 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
design_list = [] # 先按照design的思路进行追踪
# 查询第一轮次
project_round_one = project_qs.pField.filter(key=0).first()
testType_list, last_chapter_items = create_csx_chapter_dict(project_round_one)
testType_list, last_chapter_items = create_csx_chapter_dict(project_round_one) # type:ignore
# 找出第一轮的研总
yz_dut = project_round_one.rdField.filter(type='YZ').first()
yz_dut = project_round_one.rdField.filter(type='YZ').first() # type:ignore
if yz_dut:
# 查询出验证所有design
yz_designs = yz_dut.rsField.all()
@@ -843,7 +843,7 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
str(test_item_last_chapter)])
test_item_dict = {'name': test_item.name, 'chapter': test_chapter,
'ident': reveal_ident}
design_dict['test_demand'].append(test_item_dict)
design_dict['test_demand'].append(test_item_dict) # type:ignore
design_list.append(design_dict)
try:
design_list = sorted(design_list, key=chapter_key)
@@ -889,7 +889,7 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
str(test_item_last_chapter)])
test_item_dict = {'name': test_item.name, 'chapter': test_chapter,
'ident': reveal_ident}
design_dict['test_demand'].append(test_item_dict)
design_dict['test_demand'].append(test_item_dict) # type:ignore
design_list.append(design_dict)
if xq_dut:
@@ -912,7 +912,7 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
str(test_item_last_chapter)])
test_item_dict = {'name': test_item.name, 'chapter': test_chapter,
'ident': reveal_ident}
design_dict['test_demand'].append(test_item_dict)
design_dict['test_demand'].append(test_item_dict) # type:ignore
design_list.append(design_dict)
# 根据design的chapter排序-为防止报错崩溃使用try-但难排查
@@ -933,10 +933,10 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
test_item_prefix = '6.2'
# 取出第一轮所有测试项的章节处理列表和字典
project_round_one = project_qs.pField.filter(key=0).first()
testType_list, last_chapter_items = create_csx_chapter_dict(project_round_one)
testType_list, last_chapter_items = create_csx_chapter_dict(project_round_one) # type:ignore
# 查询第一轮所有测试项
test_items = []
test_items.extend(project_round_one.rtField.all())
test_items.extend(project_round_one.rtField.all()) # type:ignore
# 最后渲染列表
items_list = []
for test_item in test_items: