增加批量增加用例、测试项、设计需求功能

This commit is contained in:
2025-12-19 18:08:19 +08:00
parent f3806687b0
commit 3e048ea876
235 changed files with 1984 additions and 201 deletions

View File

@@ -8,8 +8,9 @@ from utils.chen_pagination import MyPagination
from django.db import transaction
from django.shortcuts import get_object_or_404
from django.db.models.functions import Replace
from django.db.models import Q, F, Value
from django.db.models import F, Value
from typing import List
from django.utils import timezone
from utils.chen_response import ChenResponse
from utils.chen_crud import multi_delete_case
from apps.project.models import Design, Dut, Round, TestDemand, Case, CaseStep, Project, Problem
@@ -20,8 +21,9 @@ from utils.util import get_testType
from utils.codes import HTTP_INDEX_ERROR, HTTP_EXISTS_CASES
from apps.project.tools.copyCase import case_move_to_test, case_copy_to_test, case_to_case_copy_or_move
from utils.smallTools.interfaceTools import conditionNoneToBlank
from apps.project.tool.batchTools import parse_case_content_string
# 导入case的schema
from apps.project.schemas.case import CaseModelOutSchemaWithoutProblem
from apps.project.schemas.case import CaseModelOutSchemaWithoutProblem, BatchCreateCaseInputSchema
@api_controller("/project", auth=JWTAuth(), permissions=[IsAuthenticated], tags=['测试用例接口'])
class CaseController(ControllerBase):
@@ -120,7 +122,7 @@ class CaseController(ControllerBase):
@transaction.atomic
def create_case(self, payload: CaseCreateInputSchema):
asert_dict = payload.dict(exclude_none=True)
# 构造design_key
# 构造demand_key
test_whole_key = "".join(
[payload.round_key, "-", payload.dut_key, '-', payload.design_key, '-', payload.test_key])
# 查询当前key应该为多少
@@ -157,6 +159,52 @@ class CaseController(ControllerBase):
CaseStep.objects.bulk_create(data_list) # type:ignore
return qs
# 批量新增用例
@route.post("/case/multi_save", url_name="case-batch-create")
@transaction.atomic
def multi_case_save(self, payload: BatchCreateCaseInputSchema):
project_obj = get_object_or_404(Project, id=payload.project_id)
user_name = self.context.request.user.name
keys = []
demands = project_obj.ptField.all() # 当前项目所有测试项
for case_data in payload.cases:
# 解析放在前面防止出错
stepsOrErrorResponse = parse_case_content_string(case_data.test_step)
if isinstance(stepsOrErrorResponse, ChenResponse):
return stepsOrErrorResponse
# 查询当前测试项下case数量以设置case的key
demand_key = case_data.parent_key
demand_obj = demands.filter(key=demand_key).first()
case_count = demand_obj.tcField.count()
key_string = ''.join([demand_key, "-", str(case_count)])
keys.append(key_string)
case_dict = {
"ident": demand_obj.ident,
"name": case_data.name,
"key": key_string,
"initialization": case_data.initialization,
"premise": case_data.premise,
"summarize": case_data.summarize,
"designPerson": user_name,
"testPerson": user_name,
"monitorPerson": user_name,
"project": project_obj,
"round": demand_obj.round,
"dut": demand_obj.dut,
"design": demand_obj.design,
"test": demand_obj,
"exe_time": timezone.now(),
"timing_diagram": case_data.sequence,
"title": case_data.name
}
case_new_obj = Case.objects.create(**case_dict)
case_step_list = []
for step in stepsOrErrorResponse:
case_step_list.append(CaseStep(**{"case": case_new_obj, "operation": step['operation'],
"expect": step['expect']}))
CaseStep.objects.bulk_create(case_step_list)
return ChenResponse(code=60000, status=200, data=keys, message='成功录入用例')
# 更新测试用例
@route.put("/case/update/{id}", response=CaseCreateOutSchema, url_name="case-update")
@transaction.atomic
@@ -283,7 +331,6 @@ class CaseController(ControllerBase):
@route.post("/case/replace/", url_name='case-replace')
@transaction.atomic
def replace_case_step_content(self, payload: ReplaceCaseSchema):
print(payload)
# 1.首先查询项目
project_obj: Project = get_object_or_404(Project, id=payload.project_id)
# 2.查询[所有轮次]的selectRows的id

View File

@@ -20,6 +20,7 @@ from apps.project.schemas.design import DeleteSchema, DesignFilterSchema, Design
ReplaceDesignContentSchema
from apps.project.tools.delete_change_key import design_delete_sub_node_key
from utils.smallTools.interfaceTools import conditionNoneToBlank
from apps.project.tools.auto_create_data import auto_create_renji
@api_controller("/project", auth=JWTAuth(), permissions=[IsAuthenticated], tags=['设计需求数据'])
class DesignController(ControllerBase):
@@ -162,7 +163,7 @@ class DesignController(ControllerBase):
design_delete_sub_node_key(single_qs)
return ChenResponse(message="设计需求删除成功!")
# 给复制功能级联选择器查询所有的设计需求
# 给复制功能级联选择器查询所有的设计需求【这是查项目所有的设计需求】
@route.get("/designDemand/getRelatedDesign", url_name='dut-relatedDesign')
def getRelatedDesign(self, id: int):
project_qs = get_object_or_404(Project, id=id)
@@ -196,3 +197,15 @@ class DesignController(ControllerBase):
# 4.提交更新
replace_count = design_qs.update(**replace_kwargs)
return {'count': replace_count}
# 点击生成人机交互界面测试-注意必须要有界面的软件
@route.get("/create_renji/", url_name='renji')
@transaction.atomic
def create_rj(self, round_id: int, project_id: int):
user_name = self.context.request.user.name # 获取当前用户名
project_obj: Project = get_object_or_404(Project, id=project_id)
dut_qs = Dut.objects.filter(round__key=round_id, project=project_obj, type='XQ').first()
if dut_qs:
auto_create_renji(user_name, dut_qs, project_obj)
return ChenResponse(status=200, message='自动生成人机界面交互测试成功!', data=dut_qs.key)
return ChenResponse(status=402, message='您还未录入需求规格说明文档,请录入后再试')

View File

@@ -1,3 +1,5 @@
from multiprocessing.spawn import old_main_modules
from ninja_extra import api_controller, ControllerBase, route
from ninja import Query
from ninja_jwt.authentication import JWTAuth
@@ -17,13 +19,15 @@ from apps.project.models import Design, Dut, Round, TestDemand, TestDemandConten
from apps.project.schemas.testDemand import DeleteSchema, TestDemandModelOutSchema, TestDemandFilterSchema, \
TestDemandTreeReturnSchema, TestDemandTreeInputSchema, TestDemandCreateOutSchema, \
TestDemandCreateInputSchema, ReplaceDemandContentSchema, PriorityReplaceSchema, \
TestDemandRelatedSchema, TestDemandExistRelatedSchema, DemandCopyToDesignSchema
TestDemandRelatedSchema, TestDemandExistRelatedSchema, DemandCopyToDesignSchema, \
TestDemandMultiCreateInputSchema
# 导入ORM
from apps.project.models import Project
# 导入工具
from apps.project.tools.copyDemand import demand_copy_to_design
from apps.project.tools.delete_change_key import demand_delete_sub_node_key
from utils.smallTools.interfaceTools import conditionNoneToBlank
from apps.project.tool.batchTools import parse_test_content_string
@api_controller("/project", auth=JWTAuth(), permissions=[IsAuthenticated], tags=['测试项接口'])
class TestDemandController(ControllerBase):
@@ -134,13 +138,13 @@ class TestDemandController(ControllerBase):
asert_dict.pop("dut_key")
asert_dict.pop("design_key")
asert_dict.pop("testContent")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 创建测试项 - 以及子项/子项步骤
qs = TestDemand.objects.create(**asert_dict)
for item in payload.dict()['testContent']:
content_obj = TestDemandContent.objects.create(
testDemand=qs,
subName=item['subName']
subName=item['subName'],
subDescription=item['subDescription']
)
TestDemandContentStep.objects.bulk_create([
TestDemandContentStep(
@@ -151,6 +155,69 @@ class TestDemandController(ControllerBase):
])
return qs
# 批量新增测试项
@route.post("/testDemand/multi_save", url_name="testDemand-multi-create")
@transaction.atomic
def create_multi_test_demand(self, payload: TestDemandMultiCreateInputSchema):
# 1.首先判断测试项标识是否重复
project_qs = Project.objects.filter(id=payload.project_id).first()
designs = project_qs.psField.all()
## 给返回response的data数据以便前端更新树状目录
keys = []
## 遍历payload.demands数组
for index, demandOne in enumerate(payload.demands):
if demandOne.ident and project_qs:
old_obj = project_qs.ptField.filter(ident=demandOne.ident).first()
if old_obj and old_obj.testType == demandOne.testType:
message_temp = f"{index}个测试项标识重复,请修改"
return ChenResponse(status=200, code=500101, data=index, message=message_temp)
# 标识不重复就开始录入了
for index, demand in enumerate(payload.demands):
create_sub_demands = parse_test_content_string(demand.testContent)
if isinstance(create_sub_demands, ChenResponse):
return create_sub_demands
else:
# 这说明解析成功了
# 首先查询所属design、dut、round方便新增
design_obj: Design = designs.filter(key=demand.parent_key).first() # 因为前端限制必然有
dut_obj = design_obj.dut
round_obj = design_obj.round
test_demand_count = TestDemand.objects.filter(project=project_qs,
design=design_obj).count()
key_string = ''.join([design_obj.key, "-", str(test_demand_count)])
keys.append(key_string)
create_demand_dict = {
'ident': demand.ident,
'name': demand.name,
'adequacy': demand.adequacy,
'priority': demand.priority,
'testType': demand.testType,
'testMethod': demand.testMethod,
'title': demand.name,
'key': key_string,
'project': project_qs,
'round': round_obj,
'dut': dut_obj,
'design': design_obj,
'testDesciption': demand.testDesciption
}
demand_created = TestDemand.objects.create(**create_demand_dict)
# 录入测试子项
for sub in create_sub_demands:
content_obj = TestDemandContent.objects.create(
testDemand=demand_created,
subName=sub['subName'],
subDescription=sub['subDescription']
)
TestDemandContentStep.objects.bulk_create([
TestDemandContentStep(
testDemandContent=content_obj,
**step.dict() if not isinstance(step, dict) else step
)
for step in sub['subStep']
])
return ChenResponse(code=200991, status=200, data=keys, message='成功录入')
# 更新测试项
@route.put("/testDemand/update/{id}", response=TestDemandCreateOutSchema, url_name="testDemand-update")
@transaction.atomic
@@ -184,7 +251,8 @@ class TestDemandController(ControllerBase):
if item['subName']:
content_obj = TestDemandContent.objects.create(
testDemand=testDemand_qs,
subName=item["subName"]
subName=item["subName"],
subDescription=item["subDescription"]
)
TestDemandContentStep.objects.bulk_create([
TestDemandContentStep(
@@ -224,7 +292,7 @@ class TestDemandController(ControllerBase):
demand_delete_sub_node_key(single_qs) # 删除后需重排子节点
return ChenResponse(message="测试需求删除成功!")
# 查询一个项目的所有测试项
# 查询一个项目的所有测试项【当前轮次】
@route.get("/testDemand/getRelatedTestDemand", url_name="testDemand-getRelatedTestDemand")
@transaction.atomic
def getRelatedTestDemand(self, id: int, round: str):
@@ -236,7 +304,7 @@ class TestDemandController(ControllerBase):
for design in designs:
design_dict = {'label': design.name, 'value': design.id, 'children': []}
for test_item in design.dtField.all():
test_item_dict = {'label': test_item.name, 'value': test_item.id}
test_item_dict = {'label': test_item.name, 'value': test_item.id, 'key': test_item.key}
design_dict['children'].append(test_item_dict)
data_list.append(design_dict)
return ChenResponse(message='获取成功', data=data_list)

View File

@@ -0,0 +1,18 @@
# Generated by Django 6.0 on 2025-12-15 09:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('project', '0017_alter_testdemandcontentstep_id'),
]
operations = [
migrations.AddField(
model_name='testdemandcontent',
name='subDescription',
field=models.CharField(blank=True, max_length=1024, null=True, verbose_name='测试子项一句话描述'),
),
]

View File

@@ -13,12 +13,15 @@ class Project(CoreModel):
objects = models.Manager()
ident = models.CharField(max_length=64, blank=True, null=True, verbose_name="项目标识",
help_text="项目标识", unique=True) # 唯一
name = models.CharField(max_length=100, blank=True, null=True, verbose_name="项目名称", help_text="项目名称")
name = models.CharField(max_length=100, blank=True, null=True, verbose_name="项目名称",
help_text="项目名称")
beginTime = models.DateField(auto_now_add=True, null=True, blank=True, help_text="开始时间",
verbose_name="开始时间")
endTime = models.DateField(auto_now_add=True, null=True, blank=True, help_text="结束时间", verbose_name="结束时间")
endTime = models.DateField(auto_now_add=True, null=True, blank=True, help_text="结束时间",
verbose_name="结束时间")
duty_person = models.CharField(max_length=64, verbose_name="负责人", help_text="负责人")
member = models.JSONField(null=True, blank=True, help_text="项目成员", verbose_name="项目成员", default=create_list)
member = models.JSONField(null=True, blank=True, help_text="项目成员", verbose_name="项目成员",
default=create_list)
# 8月新增字段
quality_person = models.CharField(max_length=64, verbose_name="质量保证员", help_text="质量保证员")
vise_person = models.CharField(max_length=64, verbose_name="质量监督员", help_text="质量监督员")
@@ -30,7 +33,8 @@ class Project(CoreModel):
default=create_list)
plant_type = models.JSONField(null=True, blank=True, help_text="平台类型", verbose_name="平台类型",
default=create_list)
report_type = models.CharField(max_length=64, blank=True, null=True, verbose_name="报告类型", help_text="报告类型")
report_type = models.CharField(max_length=64, blank=True, null=True, verbose_name="报告类型",
help_text="报告类型")
language = models.JSONField(null=True, blank=True, help_text="被测语言", verbose_name="被测语言",
default=create_list)
standard = models.JSONField(null=True, blank=True, help_text="依据标准", verbose_name="依据标准",
@@ -56,10 +60,12 @@ class Project(CoreModel):
help_text="测评中心电话")
test_email = models.CharField(max_length=64, blank=True, null=True, verbose_name="测评中心邮箱",
help_text="测评中心邮箱")
step = models.CharField(max_length=8, blank=True, null=True, verbose_name="项目阶段", help_text="项目阶段")
step = models.CharField(max_length=8, blank=True, null=True, verbose_name="项目阶段",
help_text="项目阶段")
abbreviation = models.JSONField(null=True, blank=True, help_text="缩略语", verbose_name="缩略语",
default=create_list)
soft_type = models.SmallIntegerField(verbose_name='软件类型', choices=((1, '新研'), (2, '改造'), (3, '沿用')),
soft_type = models.SmallIntegerField(verbose_name='软件类型',
choices=((1, '新研'), (2, '改造'), (3, '沿用')),
default=1)
runtime = models.CharField(max_length=8, blank=True, null=True, verbose_name="运行环境",
help_text="运行环境")
@@ -85,23 +91,31 @@ class Round(CoreModel):
help_text="轮次名称")
beginTime = models.DateField(auto_now_add=True, null=True, blank=True, help_text="开始时间",
verbose_name="开始时间")
endTime = models.DateField(auto_now_add=True, null=True, blank=True, help_text="结束时间", verbose_name="结束时间")
grade = models.CharField(max_length=64, blank=True, null=True, verbose_name="等级", help_text="等级", default='1')
best_condition_voltage = models.CharField(max_length=64, blank=True, null=True, verbose_name="最优工况电压",
endTime = models.DateField(auto_now_add=True, null=True, blank=True, help_text="结束时间",
verbose_name="结束时间")
grade = models.CharField(max_length=64, blank=True, null=True, verbose_name="等级", help_text="等级",
default='1')
best_condition_voltage = models.CharField(max_length=64, blank=True, null=True,
verbose_name="最优工况电压",
help_text="最优工况电压")
best_condition_tem = models.CharField(max_length=64, blank=True, null=True, verbose_name="最优工况温度",
help_text="最优工况温度")
typical_condition_voltage = models.CharField(max_length=64, blank=True, null=True, verbose_name="典型工况电压",
typical_condition_voltage = models.CharField(max_length=64, blank=True, null=True,
verbose_name="典型工况电压",
help_text="典型工况电压")
typical_condition_tem = models.CharField(max_length=64, blank=True, null=True, verbose_name="典型工况温度",
typical_condition_tem = models.CharField(max_length=64, blank=True, null=True,
verbose_name="典型工况温度",
help_text="典型工况温度")
low_condition_voltage = models.CharField(max_length=64, blank=True, null=True, verbose_name="最低工况电压",
low_condition_voltage = models.CharField(max_length=64, blank=True, null=True,
verbose_name="最低工况电压",
help_text="最低工况电压")
low_condition_tem = models.CharField(max_length=64, blank=True, null=True, verbose_name="最低工况温度",
help_text="最低工况温度")
project = models.ForeignKey(to="Project", db_constraint=False, related_name="pField", on_delete=models.CASCADE,
project = models.ForeignKey(to="Project", db_constraint=False, related_name="pField",
on_delete=models.CASCADE,
verbose_name='归属项目', help_text='归属项目', related_query_name='pQuery')
level = models.CharField(max_length=15, verbose_name='树状级别第一级', help_text="树状级别第一级", default='0')
level = models.CharField(max_length=15, verbose_name='树状级别第一级', help_text="树状级别第一级",
default='0')
key = models.CharField(max_length=15, verbose_name='给前端的树状级别', help_text="给前端的树状级别")
title = models.CharField(max_length=15, verbose_name='给前端的name', help_text="给前端的name")
# 新增执行地点
@@ -120,30 +134,38 @@ class Dut(CoreModel):
objects = models.Manager()
ident = models.CharField(max_length=64, blank=True, null=True, verbose_name="被测件标识",
help_text="被测件标识") # 后面加上unique=True
type = models.CharField(max_length=16, blank=True, null=True, verbose_name="被测件类型", help_text="被测件类型")
name = models.CharField(max_length=64, blank=True, null=True, verbose_name="被测件名称", help_text="被测件名称")
type = models.CharField(max_length=16, blank=True, null=True, verbose_name="被测件类型",
help_text="被测件类型")
name = models.CharField(max_length=64, blank=True, null=True, verbose_name="被测件名称",
help_text="被测件名称")
# 2025年4月28日更新分为总函数、有效代码行数、注释行数
total_lines = models.CharField(max_length=64, blank=True, null=True, verbose_name='总行数')
effective_lines = models.CharField(max_length=64, blank=True, null=True, verbose_name='有效代码行数')
comment_lines = models.CharField(max_length=64, blank=True, null=True, verbose_name='注释行数')
# 更新结束
title = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-名称", help_text="树-名称")
title = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-名称",
help_text="树-名称")
key = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-key", help_text="树-key")
# 被测件添加版本、发布单位、发布时间
version = models.CharField(max_length=64, blank=True, null=True, verbose_name="发布版本", help_text="发布版本")
version = models.CharField(max_length=64, blank=True, null=True, verbose_name="发布版本",
help_text="发布版本")
release_union = models.CharField(max_length=64, blank=True, null=True, verbose_name="发布版本",
help_text="发布版本")
release_date = models.DateField(auto_now_add=True, null=True, blank=True, help_text="发布时间",
verbose_name="发布时间")
# 新增用户文档的编号
ref = models.CharField(max_length=32, blank=True, null=True, verbose_name="文档编号", help_text="文档编号")
ref = models.CharField(max_length=32, blank=True, null=True, verbose_name="文档编号",
help_text="文档编号")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
level = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-level", help_text="树-level",
level = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-level",
help_text="树-level",
default=1) # 默认为1
project = models.ForeignKey(to="Project", db_constraint=False, related_name="pdField", on_delete=models.CASCADE,
project = models.ForeignKey(to="Project", db_constraint=False, related_name="pdField",
on_delete=models.CASCADE,
verbose_name='归属项目', help_text='归属项目', related_query_name='pdQuery')
round = models.ForeignKey(to="Round", db_constraint=False, related_name="rdField", on_delete=models.CASCADE,
round = models.ForeignKey(to="Round", db_constraint=False, related_name="rdField",
on_delete=models.CASCADE,
verbose_name='归属轮次', help_text='归属轮次', related_query_name='rdQuery')
def __str__(self):
@@ -159,7 +181,8 @@ class DutMetrics(models.Model):
objects = models.Manager()
id = ShortUUIDField(primary_key=True, help_text="id", verbose_name="id")
# 外键Dut一个Dut储存一个指标
dut = models.OneToOneField(Dut, on_delete=models.CASCADE, related_name='metrics', related_query_name='metrics',
dut = models.OneToOneField(Dut, on_delete=models.CASCADE, related_name='metrics',
related_query_name='metrics',
db_constraint=False, verbose_name='归属源代码被测件')
avg_function_lines = models.IntegerField(verbose_name='平均模块大小')
avg_cyclomatic = models.IntegerField(verbose_name='平均圈复杂度')
@@ -173,19 +196,25 @@ class Design(CoreModel):
objects = models.Manager()
ident = models.CharField(max_length=64, blank=True, null=True, verbose_name="设计需求标识",
help_text="设计需求标识")
name = models.CharField(max_length=64, blank=True, null=True, verbose_name="设计需求名称", help_text="设计需求名称")
name = models.CharField(max_length=64, blank=True, null=True, verbose_name="设计需求名称",
help_text="设计需求名称")
demandType = models.CharField(max_length=8, blank=True, null=True, verbose_name="设计需求类型",
help_text="设计需求类型")
description = HTMLField(blank=True, null=True, verbose_name="设计需求描述", help_text="设计需求描述")
title = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-名称", help_text="树-名称")
title = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-名称",
help_text="树-名称")
key = models.CharField(max_length=64, blank=True, null=True, verbose_name="round-dut-designkey",
help_text="round-dut-designkey")
level = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-level", help_text="树-level",
level = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-level",
help_text="树-level",
default=2) # 默认为2
chapter = models.CharField(max_length=64, blank=True, verbose_name="设计需求章节号", help_text="设计需求章节号")
project = models.ForeignKey(to="Project", db_constraint=False, related_name="psField", on_delete=models.CASCADE,
chapter = models.CharField(max_length=64, blank=True, verbose_name="设计需求章节号",
help_text="设计需求章节号")
project = models.ForeignKey(to="Project", db_constraint=False, related_name="psField",
on_delete=models.CASCADE,
verbose_name='归属项目', help_text='归属项目', related_query_name='psQuery')
round = models.ForeignKey(to="Round", db_constraint=False, related_name="dsField", on_delete=models.CASCADE,
round = models.ForeignKey(to="Round", db_constraint=False, related_name="dsField",
on_delete=models.CASCADE,
verbose_name='归属轮次', help_text='归属轮次', related_query_name='rsQuery')
dut = models.ForeignKey(to="Dut", db_constraint=False, related_name="rsField", on_delete=models.CASCADE,
verbose_name='归属轮次', help_text='归属轮次', related_query_name='rsQuery')
@@ -214,29 +243,42 @@ class TestDemand(CoreModel):
"""测试项"""
ident = models.CharField(max_length=64, blank=True, null=True, verbose_name="测试需求标识",
help_text="测试需求标识")
name = models.CharField(max_length=64, blank=True, null=True, verbose_name="测试需求名称", help_text="测试需求名称")
adequacy = models.CharField(max_length=256, blank=True, null=True, verbose_name="充分条件", help_text="充分条件")
priority = models.CharField(max_length=8, blank=True, null=True, verbose_name="优先级", help_text="优先级")
testType = models.CharField(max_length=8, null=True, blank=True, help_text="测试类型", verbose_name="测试类型",
name = models.CharField(max_length=64, blank=True, null=True, verbose_name="测试需求名称",
help_text="测试需求名称")
adequacy = models.CharField(max_length=256, blank=True, null=True, verbose_name="充分条件",
help_text="充分条件")
priority = models.CharField(max_length=8, blank=True, null=True, verbose_name="优先级",
help_text="优先级")
testType = models.CharField(max_length=8, null=True, blank=True, help_text="测试类型",
verbose_name="测试类型",
default="1")
testMethod = models.JSONField(blank=True, help_text="测试方法", verbose_name="测试方法", default=create_list)
title = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-名称", help_text="树-名称")
key = models.CharField(max_length=64, blank=True, null=True, verbose_name="round-dut-designkey-testdemand",
testMethod = models.JSONField(blank=True, help_text="测试方法", verbose_name="测试方法",
default=create_list)
title = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-名称",
help_text="树-名称")
key = models.CharField(max_length=64, blank=True, null=True,
verbose_name="round-dut-designkey-testdemand",
help_text="round-dut-designkey-testdemand")
level = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-level", help_text="树-level",
level = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-level",
help_text="树-level",
default=3) # 默认为3
project = models.ForeignKey(to="Project", db_constraint=False, related_name="ptField", on_delete=models.CASCADE,
project = models.ForeignKey(to="Project", db_constraint=False, related_name="ptField",
on_delete=models.CASCADE,
verbose_name='归属项目', help_text='归属项目', related_query_name='ptQuery')
round = models.ForeignKey(to="Round", db_constraint=False, related_name="rtField", on_delete=models.CASCADE,
round = models.ForeignKey(to="Round", db_constraint=False, related_name="rtField",
on_delete=models.CASCADE,
verbose_name='归属轮次', help_text='归属轮次', related_query_name='dutQuery')
dut = models.ForeignKey(to="Dut", db_constraint=False, related_name="dutField", on_delete=models.CASCADE,
verbose_name='归属被测件', help_text='归属被测件', related_query_name='dtQuery')
design = models.ForeignKey(to="Design", db_constraint=False, related_name="dtField", on_delete=models.CASCADE,
verbose_name='归属设计需求', help_text='归属设计需求', related_query_name='dtQuery')
design = models.ForeignKey(to="Design", db_constraint=False, related_name="dtField",
on_delete=models.CASCADE,
verbose_name='归属设计需求', help_text='归属设计需求',
related_query_name='dtQuery')
otherDesign = models.ManyToManyField(to="Design", db_constraint=False, related_name="odField",
related_query_name='odQuery', blank=True)
# 新模版要求:测试项描述对整个测试项进行描述
testDesciption = models.CharField(max_length=1024, blank=True, null=True, verbose_name='测试项描述', default="",
testDesciption = models.CharField(max_length=1024, blank=True, null=True, verbose_name='测试项描述',
default="",
help_text='测试项描述')
def __str__(self):
@@ -246,11 +288,15 @@ class TestDemandContent(CoreModel):
objects = models.Manager()
"""测试方法中的测试子项内容"""
testDemand = models.ForeignKey(to="TestDemand", db_constraint=False, related_name="testQField",
on_delete=models.CASCADE, verbose_name='归属的测试项', help_text='归属的测试项',
on_delete=models.CASCADE, verbose_name='归属的测试项',
help_text='归属的测试项',
related_query_name='testQField')
# 2025年4月16去掉subDesc、condition、observe
# 4月17修改因为新增步骤所以把operation和expect弄到下面Model里面了新增字段
# 2025/4/16去掉subDesc、condition、observe
# 2025/4/17修改因为新增步骤所以把operation和expect弄到下面Model里面了新增字段
subName = models.CharField(max_length=1024, blank=True, null=True, verbose_name='测试子项名称')
# 2025/12/15修改CPU新增“测试子项描述”FPGA渲染单个
subDescription = models.CharField(max_length=1024, blank=True, null=True,
verbose_name='测试子项一句话描述')
def __str__(self):
return f'测试子项:{self.subName}'
@@ -260,38 +306,55 @@ class TestDemandContentStep(CoreModel):
objects = models.Manager()
operation = models.CharField(max_length=3072, blank=True, null=True, verbose_name='测试子项操作')
expect = models.CharField(max_length=1024, blank=True, null=True, verbose_name='期望')
testDemandContent = models.ForeignKey(to="TestDemandContent", db_constraint=False, related_name="testStepField",
testDemandContent = models.ForeignKey(to="TestDemandContent", db_constraint=False,
related_name="testStepField",
on_delete=models.CASCADE, verbose_name='归属的测试项',
help_text='归属的测试项',
related_query_name='testStepField')
class Case(CoreModel):
objects = models.Manager()
ident = models.CharField(max_length=64, blank=True, null=True, verbose_name="用例标识", help_text="用例标识")
name = models.CharField(max_length=64, blank=True, null=True, verbose_name="用例名称", help_text="用例名称")
ident = models.CharField(max_length=64, blank=True, null=True, verbose_name="用例标识",
help_text="用例标识")
name = models.CharField(max_length=64, blank=True, null=True, verbose_name="用例名称",
help_text="用例名称")
initialization = models.CharField(max_length=128, blank=True, null=True, verbose_name="初始条件",
help_text="初始化条件")
premise = models.CharField(max_length=128, blank=True, null=True, verbose_name="前提和约束", help_text="前提和约束")
summarize = models.CharField(max_length=256, blank=True, null=True, verbose_name="用例综述", help_text="用例综述")
designPerson = models.CharField(max_length=16, blank=True, null=True, verbose_name="设计人员", help_text="设计人员")
testPerson = models.CharField(max_length=16, blank=True, null=True, verbose_name="测试人员", help_text="测试人员")
premise = models.CharField(max_length=128, blank=True, null=True, verbose_name="前提和约束",
help_text="前提和约束")
summarize = models.CharField(max_length=256, blank=True, null=True, verbose_name="用例综述",
help_text="用例综述")
designPerson = models.CharField(max_length=16, blank=True, null=True, verbose_name="设计人员",
help_text="设计人员")
testPerson = models.CharField(max_length=16, blank=True, null=True, verbose_name="测试人员",
help_text="测试人员")
monitorPerson = models.CharField(max_length=16, blank=True, null=True, verbose_name="审核人员",
help_text="审核人员")
project = models.ForeignKey(to="Project", db_constraint=False, related_name="pcField", on_delete=models.CASCADE,
project = models.ForeignKey(to="Project", db_constraint=False, related_name="pcField",
on_delete=models.CASCADE,
verbose_name='归属项目', help_text='归属项目', related_query_name='pcQuery')
isLeaf = models.BooleanField(default=True, verbose_name="树状图最后一个节点", help_text="树状图最后一个节点")
round = models.ForeignKey(to="Round", db_constraint=False, related_name="rcField", on_delete=models.CASCADE,
isLeaf = models.BooleanField(default=True, verbose_name="树状图最后一个节点",
help_text="树状图最后一个节点")
round = models.ForeignKey(to="Round", db_constraint=False, related_name="rcField",
on_delete=models.CASCADE,
verbose_name='归属轮次', help_text='归属轮次', related_query_name='rcQuery')
dut = models.ForeignKey(to="Dut", db_constraint=False, related_name="ducField", on_delete=models.CASCADE,
verbose_name='归属被测件', help_text='归属被测件', related_query_name='ducQuery')
design = models.ForeignKey(to="Design", db_constraint=False, related_name="dcField", on_delete=models.CASCADE,
verbose_name='归属设计需求', help_text='归属设计需求', related_query_name='dcQuery')
test = models.ForeignKey(to="TestDemand", db_constraint=False, related_name="tcField", on_delete=models.CASCADE,
verbose_name='归属测试需求', help_text='归属测试需求', related_query_name='tcQuery')
title = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-名称", help_text="树-名称")
key = models.CharField(max_length=64, blank=True, null=True, verbose_name="round-dut-designkey-testdemand-case",
design = models.ForeignKey(to="Design", db_constraint=False, related_name="dcField",
on_delete=models.CASCADE,
verbose_name='归属设计需求', help_text='归属设计需求',
related_query_name='dcQuery')
test = models.ForeignKey(to="TestDemand", db_constraint=False, related_name="tcField",
on_delete=models.CASCADE,
verbose_name='归属测试需求', help_text='归属测试需求',
related_query_name='tcQuery')
title = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-名称",
help_text="树-名称")
key = models.CharField(max_length=64, blank=True, null=True,
verbose_name="round-dut-designkey-testdemand-case",
help_text="round-dut-designkey-testdemand-case")
level = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-level", help_text="树-level",
level = models.CharField(max_length=64, blank=True, null=True, verbose_name="树-level",
help_text="树-level",
default=4) # 默认为4
# 2024年5月31日新增属性执行时间
exe_time = models.DateField(blank=True, null=True, verbose_name='执行时间', help_text='执行时间')
@@ -310,14 +373,17 @@ class Case(CoreModel):
class CaseStep(CoreModel):
objects = models.Manager()
operation = HTMLField(blank=True, null=True, verbose_name="测试步骤-操作", help_text="测试步骤-操作")
expect = models.CharField(max_length=3072, blank=True, null=True, verbose_name="用例预期", help_text="用例预期")
expect = models.CharField(max_length=3072, blank=True, null=True, verbose_name="用例预期",
help_text="用例预期")
result = HTMLField(blank=True, null=True, verbose_name="测试步骤-结果", help_text="测试步骤-结果")
passed = models.CharField(max_length=8, null=True, blank=True, help_text="是否通过", verbose_name="是否通过",
passed = models.CharField(max_length=8, null=True, blank=True, help_text="是否通过",
verbose_name="是否通过",
default="3")
# status = models.CharField(max_length=8, null=True, blank=True, help_text="执行状态", verbose_name="执行状态",
# default="3")
case = models.ForeignKey(to="Case", db_constraint=False, related_name="step",
on_delete=models.CASCADE, verbose_name='归属的测试用例', help_text='归属的测试用例',
on_delete=models.CASCADE, verbose_name='归属的测试用例',
help_text='归属的测试用例',
related_query_name='stepQ')
def __str__(self):
@@ -326,34 +392,46 @@ class CaseStep(CoreModel):
class Problem(CoreModel):
objects = models.Manager()
# ident为PT_RXXXX_ident这里需要根据测试项类型进行排序处理
ident = models.CharField(max_length=64, blank=True, null=True, verbose_name="问题单标识", help_text="问题单标识")
name = models.CharField(max_length=64, blank=True, null=True, verbose_name="问题单名称", help_text="问题单名称")
ident = models.CharField(max_length=64, blank=True, null=True, verbose_name="问题单标识",
help_text="问题单标识")
name = models.CharField(max_length=64, blank=True, null=True, verbose_name="问题单名称",
help_text="问题单名称")
# 问题状态1-已闭环 2-开放 3-推迟 4-撤销
status = models.CharField(max_length=8, blank=True, null=True, verbose_name="缺陷状态", help_text="缺陷状态")
status = models.CharField(max_length=8, blank=True, null=True, verbose_name="缺陷状态",
help_text="缺陷状态")
# 问题等级1-一般 2-严重 3-建议 4-重大
grade = models.CharField(max_length=8, blank=True, null=True, verbose_name="缺陷等级", help_text="缺陷等级")
grade = models.CharField(max_length=8, blank=True, null=True, verbose_name="缺陷等级",
help_text="缺陷等级")
# 问题类型1-其他问题 2-文档问题 3-程序问题 4-设计问题 5-需求问题 6-数据问题
type = models.CharField(max_length=8, blank=True, null=True, verbose_name="缺陷类型", help_text="缺陷类型")
type = models.CharField(max_length=8, blank=True, null=True, verbose_name="缺陷类型",
help_text="缺陷类型")
closeMethod = models.JSONField(null=True, blank=True, help_text="闭环方式", verbose_name="闭环方式",
default=create_list_1)
operation = HTMLField(blank=True, null=True, verbose_name="问题描述", help_text="问题描述")
result = HTMLField(blank=True, null=True, verbose_name="问题结果/影响", help_text="问题结果/影响")
postPerson = models.CharField(max_length=16, blank=True, null=True, verbose_name="提出人员", help_text="提出人员")
postDate = models.DateField(auto_now_add=True, null=True, blank=True, help_text="提单日期", verbose_name="提单日期")
postPerson = models.CharField(max_length=16, blank=True, null=True, verbose_name="提出人员",
help_text="提出人员")
postDate = models.DateField(auto_now_add=True, null=True, blank=True, help_text="提单日期",
verbose_name="提单日期")
designerPerson = models.CharField(max_length=16, blank=True, null=True, verbose_name="开发人员",
help_text="开发人员")
designDate = models.DateField(auto_now_add=True, null=True, blank=True, help_text="确认日期",
verbose_name="确认日期")
verifyPerson = models.CharField(max_length=16, blank=True, null=True, verbose_name="验证人员", help_text="验证人员")
verifyPerson = models.CharField(max_length=16, blank=True, null=True, verbose_name="验证人员",
help_text="验证人员")
verifyDate = models.DateField(auto_now_add=True, null=True, blank=True, help_text="验证日期",
verbose_name="验证日期")
project = models.ForeignKey(to="Project", db_constraint=False, related_name="projField", on_delete=models.CASCADE,
project = models.ForeignKey(to="Project", db_constraint=False, related_name="projField",
on_delete=models.CASCADE,
verbose_name='归属项目', help_text='归属项目', related_query_name='projQuery')
case = models.ManyToManyField(to="Case", db_constraint=False, related_name="caseField", verbose_name='归属测试用例',
case = models.ManyToManyField(to="Case", db_constraint=False, related_name="caseField",
verbose_name='归属测试用例',
help_text='归属测试用例-多对多', related_query_name='caseQuery')
solve = models.TextField(verbose_name='开发人员填写-改正措施',
help_text='开发人员填写-改正措施该字段需要关联“status=1”', blank=True, null=True)
analysis = HTMLField(blank=True, null=True, verbose_name="开发人员填写-原因分析", help_text="开发人员填写-原因分析")
help_text='开发人员填写-改正措施该字段需要关联“status=1”', blank=True,
null=True)
analysis = HTMLField(blank=True, null=True, verbose_name="开发人员填写-原因分析",
help_text="开发人员填写-原因分析")
effect_scope = HTMLField(blank=True, null=True, verbose_name="开发人员填写-影响域分析",
help_text="开发人员填写-影响域分析")
verify_result = HTMLField(blank=True, null=True, verbose_name="回归结果", help_text="回归结果")

View File

@@ -126,6 +126,20 @@ class CaseCreateInputSchema(Schema):
# 新增时序图字段
timing_diagram: str = Field("", alias="timing_diagram")
# 批量新增测试用例
class OneCaseBatchCreateSchema(Schema):
parent_key: str
name: str
summarize: Optional[str] = ""
initialization: Optional[str] = ""
premise: Optional[str] = ""
sequence: Optional[str] = "" # 时序图
test_step: str
class BatchCreateCaseInputSchema(Schema):
project_id: int = Field(..., validation_alias=AliasChoices('project_id', 'projectId'))
cases: List[OneCaseBatchCreateSchema] = []
# 由demand创建case的输入Schema
class DemandNodeSchema(Schema):
project_id: int

View File

@@ -15,6 +15,7 @@ class TestContentStepSchema(ModelSchema):
fields = ['operation', 'expect']
class TestContentSchema(ModelSchema):
subDescription: Optional[str] = ""
subStep: List[TestContentStepSchema] = [] # 可能为空
class Meta:
@@ -76,6 +77,8 @@ class TestDemandCreateOutSchema(ModelSchema):
# 新增测试子项单个子项的Schema
class TestContentInputSchema(Schema):
subName: str = None
# 2025/12/15-对CPU增加测试子项描述
subDescription: Optional[str] = "" # 未提供时为空字符串
subStep: Optional[List[TestContentStepSchema]] = []
# 新增/更新测试项Schema
@@ -95,6 +98,22 @@ class TestDemandCreateInputSchema(Schema):
testType: str = Field(None, alias="testType")
testDesciption: str = Field("", alias='testDesciption')
# 批量新增测试项Schema-2个Schema
class TestDemandOneInput(Schema):
parent_key: str # 直接给设计需求的key前端去组装
ident: str
name: str
priority: str = "1"
adequacy: str
testContent: str # 注意这个在接口里面分情况判断
testMethod: List[str] = []
testType: str
testDesciption: Optional[str] = ""
class TestDemandMultiCreateInputSchema(Schema):
project_id: int
demands: List[TestDemandOneInput]
# 处理前端请求-设计需求关联测试需求(测试项)
class TestDemandRelatedSchema(Schema):
data: List[int] = None
@@ -129,4 +148,4 @@ class ReplaceDemandContentSchema(Schema):
# 优先级替换Schema
class PriorityReplaceSchema(Schema):
selectRows: List[int] = None
priority: str
priority: str

View File

@@ -0,0 +1,111 @@
import re
from utils.chen_response import ChenResponse
def parse_test_content_string(content: str):
"""
解析前端传来的批量新增测试项testContent字段
"""
# 判断是否为空字符串
if not content or not content.strip():
return []
create_subDemands = [] # 储存测试子项内容
current_subDemand: None | dict = None
lines = content.strip().split("\n")
line_number = 0
for i, line in enumerate(lines):
line_number = i + 1
line = line.strip()
# 跳过空行
if not line:
continue
# 检查是否以^开头
if line.startswith("^"):
# 标识一个测试子项开始了
if current_subDemand:
create_subDemands.append(current_subDemand)
# 解析新测试子项
try:
# 检查是否包含分隔符@,包含则分割
if '@' in line:
[item_name, item_desc] = line.split("@")
else:
item_name = line
item_desc = ""
# 判断名称是否为空
item_name = item_name.replace("^", "", count=1)
if not item_name:
message = f"您字符串中,第{line_number}行没有测试子项名称"
return ChenResponse(status=200, code=500102, data=line_number, message=message)
# 组装一个测试子项
current_subDemand = {
'subName': item_name,
'subDescription': item_desc,
'subStep': []
}
except Exception as e:
message = f"您字符串中,第{line_number}行解析错误,错误原因请检查"
print('解析^行报错,后台详情:', e)
return ChenResponse(status=200, code=500103, data=line_number, message=message)
elif '@' in line and current_subDemand is not None:
try:
[operation, expect] = line.split('@')
current_subDemand['subStep'].append({ # type:ignore
'operation': operation,
'expect': expect
})
except Exception as e:
message = f"{line_number}发现您子项步骤格式有问题,请检查"
print('解析步骤行报错,后台详情:', e)
return ChenResponse(status=200, code=500104, data=line_number, message=message)
else:
# 这里就是即没有^也没有@的情况,直接跳出本次循环即可
continue
# 添加最后一个测试项
if current_subDemand:
create_subDemands.append(current_subDemand)
return create_subDemands
def parse_case_content_string(content: str):
"""
解析前端传来的批量新增测试用例test_step字段
"""
# 如果为空返回空列表-不会引起错误因为前端限制
if not content or not content.strip():
return []
create_step = [] # 储存测试子项内容
current_step: None | dict = None
lines = content.strip().split("\n")
line_number = 0
for i, line in enumerate(lines):
line_number = i + 1
line = line.strip()
# 跳过空行
if not line:
continue
# 判断是否有“@”,如果没有则给用户报错
if "@" not in line:
message = f"{line_number}行没有使用@符号分割,请检查!"
return ChenResponse(status=200, code=60001, data=line_number, message=message)
# 这里必然有@组装current_step
[operation, expect] = line.strip().split("@")
# 错误处理两种情况,操作为空,预期为空
if not operation.strip():
message = f"{line_number}行@符号前面的输入内容为空,请检查!"
return ChenResponse(status=200, code=60002, data=line_number, message=message)
if not expect.strip():
message = f"{line_number}行@符号后面的预期为空,请检查!"
return ChenResponse(status=200, code=60003, data=line_number, message=message)
# 组装当前步骤行
current_step = {
"operation": operation,
"expect": expect
}
if current_step:
create_step.append(current_step)
return create_step

View File

@@ -10,6 +10,9 @@ from apps.project.models import (
CaseStep
)
# 导入人机交互界面固定数据
from apps.project.tools.rj_data_cont import rj_data
def auto_create_jt_and_dm(user_name: str, dut_qs: Dut, project_obj: Project):
"""传入源代码dut以及测试人员名称username自动在dut下面生成静态分析和代码审查设计需求、测试项、用例"""
# 先查询dut_qs下面有多少design以便写里面的key
@@ -188,20 +191,22 @@ def auto_create_wd(user_name: str, dut_qs: Dut, project_obj: Project):
'testMethod': ["3"],
'title': '文档审查',
'testDesciption': '本次文档审查包括的内容如下:\a'
'1软件研制总结报告\a'
'2软件开发计划\a'
'3软件运行方案说明\a'
'4软件接口需求规格说明\a'
'5软件系统设计说明\a'
'6软件接口设计说明\a'
'7软件需求规格说明\a'
'8软件配置项设计说明\a'
'9软件测试说明\a'
'10软件测试报告\a'
'11产品规格说明\a'
'12软件版本说明\a'
'13软件用户手册\a'
'14固件保障手册',
'1软件需求规格说明\a'
'2软件详细设计说明\a'
'3软件开发计划\a'
'4软件配置管理计划\a'
'5软件质量保证计划\a'
'6软件单元测试计划\a'
'7软件单元测试说明\a'
'8软件单元测试报告\a'
'9配置项测试计划\a'
'10配置项测试说明\a'
'11配置项测试报告\a'
'12软件用户手册\a'
'13软件研制总结报告\a'
'14软件版本说明\a'
'15软件产品规格说明\a'
'16固件保障手册',
'key': ''.join([new_wd_design_obj.key, '-', '0']),
'level': '3',
'project': project_obj,
@@ -216,7 +221,10 @@ def auto_create_wd(user_name: str, dut_qs: Dut, project_obj: Project):
operation='根据文档审查表人工逐项检查,检查此项目文档的齐套性、完整性、规范性:\a'
'1使用人工审查方法按照附录A中文档齐套性审查单检查需求类、设计类、用户类、测试类文档是否齐套\a'
'2使用人工审查方法按照附录A中需求规格说明审查单对软件需求规格说明逐项检查\a'
'3使用人工审查方法按照附录A中软件设计文档审查单逐项检查。'
'3使用人工审查方法按照附录A中软件设计文档审查单逐项检查。',
expect='被测软件文档种类齐全,内容完整,描述准确,格式规范;\a'
'2需求文档内容完整描述准确格式规范文档文文一致、文实相符\a'
'3设计说明文档内容完整描述准确格式规范文档文文一致、文实相符。',
)
new_wd_case_obj = Case.objects.create(
ident='WDSC',
@@ -247,3 +255,74 @@ def auto_create_wd(user_name: str, dut_qs: Dut, project_obj: Project):
expect='文档满足完整性、准确性、规范性和一致性的要求',
result='文档检查单全部审查通过,文档内容完整、文档描述准确、'
'文档格式规范、文档文文一致', )
def auto_create_renji(user_name: str, dut_qs: Dut, project_obj: Project):
"""传入用户名、在dut下创建、项目对象自动创建人机交互界面的设计需求、测试项、测试用例"""
# 先查询dut_qs下有多少desgin用于设置key
design_index = dut_qs.rsField.count()
for item in rj_data:
# 创建设计需求
rj_design_create_dict = {
'ident': item['ident'],
'name': item['desgin_name'],
'demandType': '6',
'description': item['xq_desc'],
'title': item['desgin_name'],
'key': ''.join([dut_qs.key, '-', str(design_index)]),
'level': '2',
'chapter': '/',
'project': project_obj,
'round': dut_qs.round,
'dut': dut_qs
}
design_index += 1
new_design_rj: Design = Design.objects.create(**rj_design_create_dict)
# 创建测试项
rj_demand_create_dict = {
'ident': item['ident'],
'name': item['test_item_name'],
'adequacy': item['chongfen'],
'priority': '2',
'testType': '12',
'testMethod': ["4"],
'testDesciption': '在界面进行观察与操作,对照需求规格说明的功能需求进行比对,对照用户手册进行比对',
'title': item['test_item_name'],
'key': ''.join([new_design_rj.key, '-', '0']),
'level': '3',
'project': project_obj,
'round': new_design_rj.round,
'dut': new_design_rj.dut,
'design': new_design_rj,
}
new_demand_rj = TestDemand.objects.create(**rj_demand_create_dict)
new_demand_content_obj = TestDemandContent.objects.create(testDemand=new_demand_rj,
subName=item['test_item_name'])
for operation in item['test_method']:
TestDemandContentStep.objects.create(testDemandContent=new_demand_content_obj,
operation=operation['caozuo']
, expect=operation['yuqi'])
# 创建测试用例
new_case_rj = Case.objects.create(
ident=item['ident'],
name=item['test_item_name'],
initialization='已获取被测件的用户手册',
premise='软件可正常运行,界面初始化完成',
summarize=item['xq_desc'],
designPerson=user_name,
testPerson=user_name,
monitorPerson=user_name,
project=project_obj,
isLeaf=True,
round=new_demand_rj.round,
dut=new_demand_rj.dut,
design=new_demand_rj.design,
test=new_demand_rj,
title=item['test_item_name'],
key=''.join([new_demand_rj.key, '-', '0']),
level='4'
)
for operation in item['test_method']:
CaseStep.objects.create(case=new_case_rj,
operation=operation['caozuo'],
expect=operation['yuqi'],
result='界面操作结果符合预期', )

View File

@@ -0,0 +1,141 @@
# 人机交互界面测试自动生成
rj_data = [
{
"desgin_name": "人机交互完整性",
"test_item_name": "人机交互完整性测试",
"ident": "WZXC",
"xq_desc": "测试软件人机交互界面的完整性",
"chongfen": "测试用例覆盖人机交互界面完整性子项要求的全部内容。\a"
"所有用例执行完毕,对于未执行的用例说明未执行原因。",
"test_method": [
{
"caozuo": "检查界面菜单名称、标签名称、按键名称的完整性",
"yuqi": "名称完整"
},
{
"caozuo": "检查界面显示区内容的完整性",
"yuqi": "显示内容完整"
},
{
"caozuo": "检查界面菜单功能的完整性",
"yuqi": "菜单功能完整"
},
]
},
{
"desgin_name": "人机交互界面一致性",
"test_item_name": "人机交互界面一致性测试",
"ident": "YZXC",
"xq_desc": "测试软件人机交互界面的一致性",
"chongfen": "测试用例覆盖人机交互界面一致性子项要求的全部内容。\a"
"所有用例执行完毕,对于未执行的用例说明未执行原因。",
"test_method": [
{
"caozuo": "检查主界面的标题栏与使用说明书的一致性",
"yuqi": "主界面的标题栏与用户手册一致"
},
{
"caozuo": "检查次级界面、对话框等标题与使用说书的一致性",
"yuqi": "次级界面、对话框等标题与用户手册一致"
},
{
"caozuo": "检查界面用语与使用说明书的一致性",
"yuqi": "界面用语与用户手册一致"
},
{
"caozuo": "检查界面的字体、颜色、位置等是否统一、字体是否对齐",
"yuqi": "界面的字体、颜色、位置等与用户手册一致"
},
{
"caozuo": "检查同类数据的显示精度是否正确、统一",
"yuqi": "同类数据的显示精度与用户手册一致,精确并统一"
},
]
},
{
"desgin_name": "人机交互界面友好性",
"test_item_name": "人机交互界面友好性测试",
"ident": "YHXC",
"xq_desc": "测试软件人机交互界面的友好性",
"chongfen": "测试用例覆盖人机交互界面友好性子项要求的全部内容。\a"
"所有用例执行完毕,对于未执行的用例说明未执行原因。",
"test_method": [
{
"caozuo": "检查界面实时显示信息区是否实时刷新",
"yuqi": "实时刷新"
},
{
"caozuo": "检查提示信息显示位置是否合理、提示框或弹窗是否居中显示",
"yuqi": "合理、弹窗居中"
},
{
"caozuo": "检查界面用语、名称等是否存在错别字、乱码等",
"yuqi": "无错别字或乱码"
},
{
"caozuo": "检查界面字符显示是否清晰",
"yuqi": "字符显示清晰"
},
{
"caozuo": "检查界面字符或提示语是否统一、汉化",
"yuqi": "统一汉化显示"
},
]
},
{
"desgin_name": "人机交互界面易操作性",
"test_item_name": "人机交互界面易操作性测试",
"ident": "YCZX",
"xq_desc": "测试软件人机交互界面的易操作性",
"chongfen": "测试用例覆盖人机交互界面易操作性子项要求的全部内容。\a"
"所有用例执行完毕,对于未执行的用例说明未执行原因。",
"test_method": [
{
"caozuo": "检查界面菜单、图标、按键等是否分布整齐、有序",
"yuqi": "分布整齐有序"
},
{
"caozuo": "检查菜单深度的合理性",
"yuqi": "菜单深度不超过3级"
},
]
},
{
"desgin_name": "人机交互界面操作测试",
"test_item_name": "人机交互界面操作测试测试",
"ident": "CZCC",
"xq_desc": "测试软件人机交互的界面操作测试",
"chongfen": "测试用例覆盖人机交互界面操作测试子项要求的全部内容。\a"
"所有用例执行完毕,对于未执行的用例说明未执行原因。",
"test_method": [
{
"caozuo": "检查按键、编辑框等使能情况(闪烁)",
"yuqi": "闪烁"
},
{
"caozuo": "执行任务期间,进行按键的多处连击",
"yuqi": "不会出现假死或崩溃"
},
{
"caozuo": "检查列表,列表中的内容允许编辑、数据变更后自动更新显示",
"yuqi": "内容允许编辑、数据变更后自动更新显示"
},
{
"caozuo": "能够进行选择和取消,选择及取消后处理正确",
"yuqi": "能够进行选择和取消,选择及取消后处理正确"
},
{
"caozuo": "选择或取消某个单选框后再进行复选操作",
"yuqi": "操作正确"
},
{
"caozuo": "执行一个任务,查看界面操作及显示的正确性",
"yuqi": "界面操作及显示正确"
},
{
"caozuo": "在一个菜单功能项执行过程中用使用按钮选择其他功能",
"yuqi": "不会出现假死或崩溃情况"
},
]
},
]