工作项解决了「做什么」,规划解决了「什么时候做」,迭代和里程碑解决了「做到什么程度算一个阶段」。但一个需求从提出到交付,还需要回答一个问题:「质量是否达标?」------用例沉淀测试设计,评审把控准入门槛,计划组织执行节奏,报告生成快照结论。这四者构成一条完整的测试质量闭环:设计 → 评审 → 执行 → 度量。本篇记录测试管理模块的数据模型、版本化机制、状态机驱动、评审策略、执行录入、报告快照、动态接入,以及前端抽屉化交互。
一、测试管理要解决什么问题
1.1 痛点:测试与研发割裂
在测试模块上线之前,平台的测试管理处于空白状态:
| 问题 | 表现 |
|---|---|
| 测试设计无处沉淀 | 用例散落在文档、Excel、本地脚本中,无法与需求/工作项关联 |
| 评审无流程 | 用例写完即用,无准入评审,质量参差不齐 |
| 执行无记录 | 测试执行是「跑一遍」的过程,结果无持久化,无法回溯 |
| 报告靠拼凑 | 手工统计通过率、缺陷数,数据滞后且易错 |
1.2 目标
用一条完整的测试质量闭环替代手工管理:
- 用例沉淀:功能目录组织用例,版本化沉淀每一次变更,关联工作项
- 评审准入:对用例版本发起评审,支持单人/多人(会签/或签),通过后冻结
- 计划执行:排期容器关联迭代/里程碑,承载用例版本与执行记录,提缺陷联动
- 报告度量:对 1~5 个计划生成统计快照,生成后数据不再变化

二、数据模型
2.1 实体总览
测试模块共 11 张表,覆盖四类实体及其关联关系:
javascript
biz_test_case ──────── biz_test_case_version(版本快照)
│ │
│ │
biz_test_case_dir biz_test_case_work_item(用例↔工作项关联)
(功能目录树) │
│
biz_test_review ──── biz_test_review_item(评审项 = 版本×评审人)
│
│(评审通过后的版本进入计划)
│
biz_test_plan ──── biz_test_plan_case(计划内用例版本)
│
├── biz_test_execution(执行记录)
│ │
│ └── biz_test_execution_step(步骤级结果)
│
└──(提缺陷 → 创建 biz_work_item + 写 biz_test_case_work_item)
biz_test_report(报告快照,含统计 JSON)
2.2 用例与版本
用例主表(biz_test_case)存储元信息,版本表(biz_test_case_version)存储每次变更的内容快照:
| 用例主表字段 | 说明 |
|---|---|
| 项目内编号 | 如 TC-0001,项目内唯一 |
| 功能目录 ID | 关联 biz_test_case_dir,空为「未分类」 |
| 标题 / 类型 / 阶段 / 优先级 | 元信息 |
| 负责人 / 自动化状态 | 管理属性 |
| 当前版本号 | 指向最新版本 |
| 归档标记 | 归档后不在列表展示 |
| 版本表字段 | 说明 |
|---|---|
| 版本号 | 用例内自增,从 1 开始 |
| 步骤 JSON | [{seq, action, expect}],JSONB 存储 |
| 前置条件 / 预期结果 / 补充说明 | Markdown |
| 状态机 ID + 发布版本号 | 创建时钉死,防状态机变更影响历史版本 |
| 当前状态码 | pending_review / reviewing / approved / rejected |
| 内容冻结标记 | 评审通过后冻结,编辑需创建新版本 |
设计要点 :用例编辑采用「写时复制」策略------当前版本为
approved(评审通过)时,编辑会创建新版本(版本号 +1),旧版本保持冻结不变;当前版本为pending_review时直接编辑当前版本;当前版本为reviewing(评审中)时禁止编辑。
2.3 评审与评审项
评审单(biz_test_review)是对一批用例版本的准入评审:
| 字段 | 说明 |
|---|---|
| 评审编号 | 如 RV-0001,项目内唯一 |
| 评审模式 | single(单人)/ multi(多人) |
| 多人策略 | countersign(会签-全部通过)/ any(或签-任一通过) |
| 状态机 | 钉死状态机 ID + 版本号,驱动生命周期 |
| 当前状态码 | not_started / in_progress / suspended / finished / cancelled |
评审项(biz_test_review_item)是评审单与用例版本的交叉表:
| 字段 | 说明 |
|---|---|
| 评审单 ID | 关联评审单 |
| 用例版本 ID | 被评审的版本 |
| 评审人 | username |
| 结论 | pending / pass / fail |
| 评审备注 | Markdown |
| 给出结论时间 | 结论锁定时记录 |
设计要点 :多人会签场景下,同一用例版本按评审人拆成多条评审项。评审结束时按策略聚合判定------会签需全部 pass 才通过,或签只需一条 pass 即通过。未给结论的评审项在结束时自动记为
fail。
2.4 计划与执行
测试计划(biz_test_plan)是测试活动的排期容器:
| 字段 | 说明 |
|---|---|
| 计划编号 | 如 TP-0001 |
| 关联迭代 ID | 敏捷场景关联迭代 |
| 关联里程碑 ID | 瀑布场景关联里程碑 |
| 产品版本 ID | 预留字段,本期不使用 |
| 计划起止日期 | 排期 |
| 状态机 | 驱动生命周期 |
计划用例(biz_test_plan_case)是计划内引用的用例版本:
| 字段 | 说明 |
|---|---|
| 计划 ID | 所属计划 |
| 用例版本 ID | 引用的版本(评审通过版本) |
| 执行人 | 指派的执行者 |
| 最新执行结果 | pass / fail / blocked / untested |
| 执行/失败/受阻次数 | 统计冗余 |
执行记录(biz_test_execution)是每次用例执行的持久化:
| 字段 | 说明 |
|---|---|
| 计划用例 ID | 关联计划用例 |
| 用例版本 ID | 执行时钉死的版本 |
| 用例级结果 | pass / fail / blocked / untested |
| 实际结果 / 备注 | Markdown |
步骤级结果(biz_test_execution_step)记录每个步骤的执行情况:
| 字段 | 说明 |
|---|---|
| 执行记录 ID | 所属执行记录 |
| 步骤序号 | 对应用例步骤 |
| 步骤结果 | pass / fail / blocked / na |
| 步骤实际结果 | 文本 |
2.5 报告快照
测试报告(biz_test_report)是生成时刻的统计快照:
| 字段 | 说明 |
|---|---|
| 关联计划 ID 列表 | JSON 数组,1~5 个 |
| 报告总结 | Markdown,可编辑 |
| 统计快照 JSON | 含用例统计、缺陷统计、执行明细、工作项列表、测试人员等 |
| 生成时间 | 快照时间戳 |
设计要点:报告采用「快照模式」------生成时从关联计划中聚合所有用例执行情况、关联工作项和缺陷,序列化为 JSON 落库。此后即使计划内数据变化,报告内容不变,需重新生成才能获取最新数据。这与里程碑/迭代的实时统计形成互补:实时统计看「现在」,报告快照看「当时」。
2.6 用例与工作项关联
关联表(biz_test_case_work_item)记录用例与工作项的多对多关系:
| 字段 | 说明 |
|---|---|
| 用例 ID | 关联用例 |
| 工作项 ID | 关联工作项(含需求/任务/缺陷) |
| 关联来源 | manual(用例表单手动关联)/ execution(执行时提缺陷自动创建) |
| 来源版本 ID | 仅 execution 场景 |
| 来源执行记录 ID | 仅 execution 场景 |
设计要点 :关联来源区分了两种关联路径------用例设计时手动关联需求/任务(
manual),执行失败时提缺陷自动关联(execution)。报告快照聚合时按此来源区分展示。

三、状态机驱动
3.1 三套独立状态机
测试模块复用平台已有的状态机框架,为三类实体各配置一套独立状态机:
| 实体 | 状态机 | 状态流转 |
|---|---|---|
| 用例版本 | test_case_version_sm |
待评审 → 评审中 → 评审通过/不通过 → (编辑创建新版本回到待评审) |
| 评审单 | test_review_sm |
未开始 → 进行中 → 已结束/已作废(可挂起/继续) |
| 测试计划 | test_plan_sm |
未开始 → 进行中 → 已结束/已作废(可挂起/继续) |
3.2 钉死机制
每个实体在创建时钉死状态机的 ID 和发布版本号(smMachineId + smVerNo),后续流转始终基于这个固定版本,防止状态机配置变更后历史实体的状态语义发生漂移。
scss
┌──────────────────────────────────────────────────┐
│ 创建评审单 │
│ │
│ 1. 从配置中心查询状态机已发布快照 │
│ cfgSmMachineMapper + smRuntimeService.pin() │
│ │
│ 2. 钉死 machineId + verNo + initialStateCode │
│ review.setSmMachineId(pin.getMachineId()) │
│ review.setSmVerNo(pin.getVerNo()) │
│ review.setStateCode(pin.getInitialStateCode()) │
│ │
│ 3. 后续流转始终使用该版本 │
│ smRuntimeService.fire(machineId, verNo, ...) │
│ → 返回目标状态码 │
│ → 更新实体 stateCode │
│ │
│ 4. 展示状态名从状态机元数据查询 │
│ stateDisplayName(smRuntimeService, ...) │
└──────────────────────────────────────────────────┘
3.3 用例版本状态联动
用例版本的状态机与评审单的生命周期联动:
| 评审操作 | 用例版本状态变化 |
|---|---|
| 添加用例版本到评审 | pending_review/rejected → reviewing(冻结) |
| 评审通过 | reviewing → approved(冻结) |
| 评审不通过 | reviewing → rejected(解冻) |
| 评审作废(撤回) | reviewing → pending_review(解冻) |
scss
┌─────────────────────────────────────────────────────┐
│ 用例版本生命周期 │
│ │
│ ┌──────────┐ 加入评审 ┌──────────┐ │
│ │ 待评审 │ ──────────────→ │ 评审中 │ │
│ │ pending │ │ reviewing │ │
│ │ _review │ ←────────────── │ (冻结) │ │
│ └────┬─────┘ 评审作废 └────┬─────┘ │
│ │ │ │
│ │ ┌─────────┼─────────┐ │
│ │ │ │ │ │
│ │ 评审通过 评审不通过 │ │
│ │ │ │ │ │
│ │ ┌────────┐ ┌────────┐ │ │
│ │ │评审通过 │ │不通过 │ │ │
│ │ │approved│ │rejected│ │ │
│ │ │(冻结) │ │(解冻) │ │ │
│ │ └───┬────┘ └───┬────┘ │ │
│ │ │ │ │ │
│ │ 编辑创建新版本 可再次编辑 │ │
│ │ │ │ │ │
│ └───────────────┴──────────┘ │ │
│ │ │
└─────────────────────────────────────────────────────┘
3.4 评审聚合判定
评审结束时,按模式与策略聚合评审项结论:
java
// 单人评审或仅一个评审人
if (SINGLE.equals(mode) || items.size() == 1) {
pass = PASS.equals(items.get(0).getConclusion());
}
// 或签:任一通过即通过
else if (ANY.equals(policy)) {
pass = items.stream().anyMatch(i -> PASS.equals(i.getConclusion()));
}
// 会签:全部通过才通过
else {
pass = items.stream().allMatch(i -> PASS.equals(i.getConclusion()));
}
聚合后触发用例版本状态机的 pass / fail 流转,同时设置冻结标记。

四、评审设计
4.1 评审模式与策略
| 模式 | 说明 | 适用场景 |
|---|---|---|
| 单人评审 | 每个用例版本只有一个评审人 | 小团队/快速迭代 |
| 多人会签 | 所有评审人都需通过才通过 | 正式发布/关键路径 |
| 多人或签 | 任一评审人通过即通过 | 时间紧迫/并行评审 |
4.2 评审准入校验
添加用例版本到评审时有多重校验:
| 校验规则 | 说明 |
|---|---|
| 版本状态校验 | 仅 pending_review / rejected 状态的版本可加入 |
| 已定稿校验 | approved 版本不可加入评审 |
| 重复占用校验 | reviewing 版本若已在其他进行中评审中,不可重复加入 |
| 冻结保护 | 加入评审后版本内容冻结,不可编辑 |
4.3 评审结束自动处理
python
┌──────────────────────────────────────────────────┐
│ 结束评审 │
│ │
│ 1. 遍历所有评审项 │
│ ├── 未给结论的 → 自动记为 fail │
│ └── 已给结论的 → 保持不变 │
│ │
│ 2. 按用例版本分组聚合 │
│ ├── 单人:取唯一结论 │
│ ├── 会签:全部 pass 才 pass │
│ └── 或签:任一 pass 即 pass │
│ │
│ 3. 触发用例版本状态机流转 │
│ ├── pass → reviewing → approved(冻结) │
│ └── fail → reviewing → rejected(解冻) │
│ │
│ 4. 触发评审单状态机 → finished │
│ 5. 记录动态 │
└──────────────────────────────────────────────────┘

五、计划与执行
5.1 计划生命周期
计划通过状态机驱动完整生命周期:
markdown
未开始 ──开始──→ 进行中 ──结束──→ 已结束
│ │ │
│ │ │
│ 挂起 不可回退
│ │
│ 挂起中 ──继续──→ 进行中
│
└──作废──→ 已作废(终态)
约束:
- 进行中才能执行用例
- 挂起状态不可执行(需先恢复)
- 已结束/已作废不可编辑结构
5.2 用例版本占用与冲突检测
同一用例版本在同一时间只能被一个未结束计划占用:
java
private boolean isVersionInActivePlan(Long caseVersionId, Long excludePlanId) {
List<TestPlanCase> planCases = testPlanCaseMapper.selectList(
new LambdaQueryWrapper<TestPlanCase>()
.eq(TestPlanCase::getCaseVersionId, caseVersionId));
Set<Long> planIds = planCases.stream()
.map(TestPlanCase::getPlanId)
.collect(Collectors.toSet());
if (excludePlanId != null) planIds.remove(excludePlanId);
// 检查这些计划是否有未结束的
for (TestPlan plan : listByIds(planIds)) {
if (isPlanNonFinal(plan)) return true;
}
return false;
}
5.3 执行录入
执行录入支持用例级和步骤级两层结果:
| 层级 | 字段 | 必填 | 说明 |
|---|---|---|---|
| 用例级 | 结果 | 是 | pass / fail / blocked / untested |
| 用例级 | 实际结果 / 备注 | 否 | Markdown |
| 步骤级 | 步骤结果 | 否 | pass / fail / blocked / na |
| 步骤级 | 步骤实际结果 | 否 | 文本 |
设计要点:步骤级结果可留空,用例级结果必填。执行后只有最新一条记录可修改,历史记录只读。执行失败/受阻时可直接提缺陷,自动创建工作项并建立用例↔缺陷关联。

5.4 提缺陷联动
ini
┌──────────────────────────────────────────────────┐
│ 执行用例 → 结果为 fail/blocked │
│ │
│ 1. 用户点击「提缺陷」 │
│ → 打开 WorkItemFormDrawer │
│ → 锁定项目 + 工作项类型=缺陷 │
│ → 预填描述(前置条件/步骤/实际结果) │
│ │
│ 2. 保存缺陷 │
│ → 创建 biz_work_item(缺陷) │
│ → 写 biz_test_case_work_item │
│ relSource = 'execution' │
│ caseVersionId = 执行时版本 │
│ executionId = 当前执行记录 │
│ │
│ 3. 缺陷出现在: │
│ ├── 计划详情「关联缺陷」Tab │
│ ├── 用例详情「关联工作项」Tab │
│ └── 报告快照「缺陷列表」+「缺陷统计」 │
└──────────────────────────────────────────────────┘
六、报告快照
6.1 生成流程
bash
┌──────────────────────────────────────────────────────┐
│ 生成报告 │
│ │
│ 1. 校验:1~5 个计划,均属于当前项目 │
│ │
│ 2. 聚合统计(buildSnapshot) │
│ ├── 遍历每个计划 → 加载计划用例 → 收集版本 ID │
│ ├── 批量加载用例版本 + 用例主表 │
│ ├── 统计执行结果分布(pass/fail/blocked/untested) │
│ ├── 聚合关联工作项(从 biz_test_case_work_item) │
│ │ ├── 区分 manual / execution 来源 │
│ │ └── 批量加载工作项 + 类型 + 状态机元数据 │
│ ├── 缺陷统计(总数/已解决/按用例分组计数) │
│ ├── 测试人员(执行人去重) │
│ └── 测试时间范围(各计划最早开始/最晚结束) │
│ │
│ 3. 序列化为 JSON → 落库 biz_test_report.snapshot │
│ │
│ 4. 记录动态 │
└──────────────────────────────────────────────────────┘
6.2 报告组件
报告详情以多组件卡片形式展示,组件顺序固定:
| 组件 | 内容 |
|---|---|
| 基本信息 | 关联计划、负责人、周期 |
| 整体概览 | 用例总数、通过率、失败/受阻/未执行数 |
| 用例结果统计 | 按计划分组表 + 计划内目录分布 |
| 缺陷概览 | 严重度分布 + 修复状态分布 |
| 人员缺陷分布 | 横向柱状图 |
| 缺陷列表 | 编号/标题/严重度/状态/负责人 |
| 工作项列表 | 关联需求/任务 |
| 执行过程概览 | 执行次数、多次失败用例 Top |
| 用例执行详情 | 明细表:用例/版本/执行人/结果/次数/备注 |
| 报告总结 | Markdown 渲染,可编辑 |


6.3 快照不可变性
报告生成后,snapshot JSON 不可变,仅 title 和 summary(Markdown 总结)可编辑。详情页顶部信息条提示:「报告为生成时刻的快照,统计不再更新。需最新数据请重新生成一份。」
七、动态接入
测试域四类实体全量接入动态模块,通过独立的 ActivityTestSupport Bean 实现注解 + 切面埋点。
7.1 作用域细分
| 实体 | scopeType | 冗余字段 |
|---|---|---|
| 用例 | TEST_CASE |
projectId |
| 计划 | TEST_PLAN |
projectId + iterationId + milestoneId |
| 评审 | TEST_REVIEW |
projectId |
| 报告 | TEST_REPORT |
projectId |
设计要点 :
scope_type使用TEST_CASE/TEST_PLAN/TEST_REVIEW/TEST_REPORT而非单一TEST,避免四类实体 ID 撞车。项目/企业动态通过冗余project_id归集。
7.2 跨域 Target 聚合
计划内「移除用例 / 指派 / 执行」与评审「提交结论」的 scope 仍属于计划/评审,但 targetType + targetId 指向用例:
ini
┌──────────────────────────────────────────────────┐
│ 用例详情动态 Tab │
│ │
│ 查询条件:targetType = 'TEST_CASE' │
│ targetId = 当前用例 ID │
│ │
│ 聚合结果(跨作用域时间线): │
│ ├── scope=TEST_CASE 创建了用例「...」 │
│ ├── scope=TEST_CASE 编辑了用例「...」 │
│ ├── scope=TEST_REVIEW 评审结论改为通过 │
│ ├── scope=TEST_PLAN 执行了用例「...」结果为通过 │
│ ├── scope=TEST_PLAN 将用例「...」指派给张明 │
│ └── scope=TEST_PLAN 将用例「...」从计划中移除 │
│ │
│ 一条用例的完整生命周期在一个时间线内展示 │
└──────────────────────────────────────────────────┘
7.3 事件目录
| 实体 | 动作 |
|---|---|
| 用例 | 创建 / 编辑 / 新版本 / 复制 / 归档 / 恢复 / 回滚 |
| 计划 | 创建 / 更新 / 复制 / 添加用例 / 移除用例 / 指派 / 取消指派 / 开始 / 挂起 / 继续 / 结束 / 作废 / 执行 / 修改执行结果 |
| 评审 | 创建 / 更新 / 添加用例版本 / 提交结论 / 开始 / 挂起 / 继续 / 结束 / 作废 |
| 报告 | 生成 / 更新 |
八、前端交互设计
8.1 模块布局
测试模块采用「左侧模块导航 + 右侧内容区」的卡片式布局:
┌──────────────────────────────────────────────────────┐
│ ┌ 模块导航 ──┐ ┌ 内容区 ────────────────────────────┐ │
│ │ │ │ │ │
│ │ 测试 │ │ PageHeader(标题 + 说明 + 新建按钮) │ │
│ │ ├ 用例 │ │ ───────────────────────────────── │ │
│ │ ├ 评审 │ │ 列表 / 详情页内容 │ │
│ │ ├ 计划 │ │ │ │
│ │ └ 报告 │ │ │ │
│ │ │ │ │ │
│ └────────────┘ └──────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
导航项与 URL query tab 同步,切换 Tab 不刷新页面。进入测试模块时隐藏项目级左侧导航,仅展示测试模块导航。
8.2 全局抽屉化
测试模块大量使用右侧抽屉(AppDrawer)承载详情,避免整页路由切换:
| 场景 | 组件 | 说明 |
|---|---|---|
| 用例新建/编辑 | TestCaseFormDrawer |
720px 抽屉,含步骤编辑器 |
| 用例预览 | TestCasePreviewDrawer |
只读预览,评审/计划中点击用例编号弹出 |
| 执行录入 | TestExecutionDrawer |
步骤级结果对照 + 提缺陷联动 |
| 报告详情 | AppDrawer + TestReportDetail |
全屏抽屉,多组件卡片长页 |
| 提缺陷 | WorkItemFormDrawer |
复用全局工作项创建组件 |

8.3 用例列表左树右表
用例列表采用知识库风格的「左树右表」布局:
- 左侧:功能目录树,支持新建/重命名/删除/搜索;树节点显示用例数
- 右侧:表格 + 筛选栏 + 分段切换(全部/我负责的/待我评审)
- 批量操作:勾选行后出现批量条------移动到目录 / 发起评审 / 归档

8.4 计划详情操作列统一下拉
计划详情的用例清单和执行记录操作列统一使用 el-dropdown,按状态动态显示可用操作:
用例清单操作列:
┌──────────────────┐
│ ⋯ 执行 │ ← 打开执行抽屉
│ 提缺陷 │ ← 打开 WorkItemFormDrawer
│ 移除 │ ← 已有执行记录时禁用 + tooltip
└──────────────────┘
执行记录操作列:
┌──────────────────┐
│ ⋯ 查看详情 │ ← 打开只读执行抽屉
│ 修改 │ ← 仅最新一条可修改
└──────────────────┘

8.5 报告详情抽屉模式
报告详情不再进入新路由,而是在报告列表页内通过 AppDrawer 全屏抽屉展示:
- 返回按钮在左上角,关闭抽屉回到列表
- 报告总结使用
MarkdownPreview渲染,点击「编辑名称/总结」切换为MarkdownEditor - 用例执行详情中点击用例编号弹出用例预览抽屉
- 工作项列表展示关联计划中的工作项与缺陷
九、设计要点总结
javascript
┌──────────────────────────────────────────────────────────────┐
│ 测试模块设计要点 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 1. 四域闭环:用例 → 评审 → 计划 → 报告 │
│ 设计沉淀 → 准入评审 → 排期执行 → 快照度量 │
│ │
│ 2. 版本化机制:写时复制,评审通过冻结 │
│ 编辑已通过版本创建新版本,旧版本保持定稿 │
│ │
│ 3. 三套状态机:用例版本 / 评审单 / 计划 │
│ 创建时钉死,状态语义不随配置变更漂移 │
│ 用例版本状态与评审单生命周期联动 │
│ │
│ 4. 评审策略:单人 / 多人会签 / 多人或签 │
│ 结束时按策略聚合,未给结论自动记不通过 │
│ │
│ 5. 执行双层级:用例级 + 步骤级 │
│ 用例级必填,步骤级可空 │
│ 仅最新一条可修改,历史只读 │
│ │
│ 6. 提缺陷联动:执行失败 → 创建工作项 + 自动关联 │
│ relSource 区分手动关联与执行关联 │
│ │
│ 7. 报告快照:生成时刻统计 JSON 落库 │
│ 1~5 个计划聚合,生成后不变,仅标题/总结可编辑 │
│ │
│ 8. 动态接入:ActivityTestSupport 独立 Bean │
│ scopeType 细分 TEST_*,target 跨域指向用例 │
│ 用例详情动态 Tab 聚合全生命周期 │
│ │
│ 9. 全局抽屉化:用例/执行/报告/提缺陷均抽屉承载 │
│ 避免整页路由切换,交互原地展开 │
│ │
│ 10. 冲突检测:用例版本同一时间仅一个未结束计划占用 │
│ 执行记录存在时不可移除用例 │
│ │
└──────────────────────────────────────────────────────────────┘