# 实战业务培训 — 测试用例

> 依据：`实战业务培训功能需求.md`、`实战业务培训技术方案.md`  
> **接口 Base Path（示例）**：`/techService/practicalTraining`；鉴权与若依一致（Cookie / Token）。

**通用前置（无特殊说明）**：具备本模块全套按钮权限的账号已登录。时间链合法样本（用于新增/修改/发布）：

| 字段 | 示例值 |
| --- | --- |
| `registrationStartTime` | `2025-08-01 08:00:00` |
| `registrationEndTime` | `2025-08-15 18:00:00` |
| `trainingTime` | `2025-08-25 09:00:00` |

**库内宜预置**（`del_flag=0`）：**T1** 未发布主题「牧业实战一期」；**T2** 已发布且报名未开始（`registration_start` 为未来）；**T3** 已发布、报名期内、`actual_enrolled_count=5`、`planned_head_count=20`；**T4** 已发布、报名期内、人数已满（`actual=20`）；**T5** 已发布、报名已截止（`registration_end` 为过去）。

**合法新增 Body（驼峰）**：`trainingTopic=牧业实战测试`，`plannedHeadCount=30`，`trainingIntro=简介文本`，`trainingLocation=县培训中心`，其余时间取上表。

**界面（UI）测试**：**Playwright** + **Chromium**（`channel: 'chrome'` 使用本机 **Google Chrome**）。

---

## 一、单元测试用例

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-SZYWPX-UT-001 | 参数校验 | 时间链 | 单元测试 | JUnit5 | §3.5 | 无 | 开始≥截止、截止≥培训、合法链 | 前两种失败；`08-01<08-15<08-25` 通过 |
| ZCZX-SZYWPX-UT-002 | 参数校验 | 培训主题 | 单元测试 | JUnit5 | 1～20 字 | 无 | 空、21 字、10 字 | 空/超长失败；合法通过 |
| ZCZX-SZYWPX-UT-003 | 参数校验 | 培训简介 trim | 单元测试 | JUnit5 | §3.3.1 | 无 | 仅空白、501 字、合法 | 空白/超长失败；通过 |
| ZCZX-SZYWPX-UT-004 | 参数校验 | 计划人数 | 单元测试 | JUnit5 | ≥1 整数 | 无 | 0、-1、1.5、30 | 非法失败；正整数通过 |
| ZCZX-SZYWPX-UT-005 | 参数校验 | 培训地点 | 单元测试 | JUnit5 | 1～200 字 | 无 | 空、201 字 | 失败/通过 |
| ZCZX-SZYWPX-UT-006 | 列表查询 | 培训日期区间 | 单元测试 | JUnit5 | §3.1.1 | 无 | `startDate>endDate`；合法闭区间 | 颠倒失败；通过 |
| ZCZX-SZYWPX-UT-007 | 报名状态 | 未发布 | 单元测试 | JUnit5 | §3.4 | `publish_status=0` | `resolve(row, now)` | `enrollStatus=1`，名称「未开始」 |
| ZCZX-SZYWPX-UT-008 | 报名状态 | 未开始/已截止 | 单元测试 | JUnit5 | §3.4 | 已发布 | `now` 早于开始；`now` 晚于截止 | 均为 `1` 或 `4` 与文档一致 |
| ZCZX-SZYWPX-UT-009 | 报名状态 | 报名中/已报满 | 单元测试 | JUnit5 | §3.4 | 已发布、在报名期内 | `actual=5,plan=20`；`actual=20,plan=20` | `006002`/`enrollStatus=2`；`006003`/`3` |
| ZCZX-SZYWPX-UT-009a | 培训状态 | 截止边界 | 单元测试 | JUnit5 | `now>=regEnd` | 已发布 | `now=registrationEndTime` | `006004` 已截止 |
| ZCZX-SZYWPX-UT-019 | 小程序报名 | 报名/取消 | 单元测试 | JUnit5+Mockito | 成员表 | Mock Mapper | `enroll`/`cancelEnroll` | 回写 `actual_enrolled_count` 与 `training_status` |
| ZCZX-SZYWPX-UT-010 | 修改未发布 | training_status 回填 | 单元测试 | JUnit5+Mockito | §2.3 | 未发布 T1；Body 不传 `trainingStatus` | `updateBizPracticalTraining` | 入库 `training_status=006001`；非 null |
| ZCZX-SZYWPX-UT-010a | 发布约束 | 已发布不可改 | 单元测试 | JUnit5+Mockito | §3.5 | `publish_status=1` | `validateForUpdate` | 失败 |
| ZCZX-SZYWPX-UT-011 | 下架约束 | 报名开始前可下架 | 单元测试 | JUnit5 | §3.5 | 已发布；`now<regStart` | `validateOffline` | 通过 |
| ZCZX-SZYWPX-UT-012 | 下架约束 | 报名开始后不可下架 | 单元测试 | JUnit5 | §3.5 | 已发布；`now≥regStart` | `validateOffline` | 失败 |
| ZCZX-SZYWPX-UT-013 | Service | 新增仅保存 | 单元测试 | JUnit5+Mockito | §3.3 | Mock Mapper | `insert` 且非 `saveAndPublish` | `publish_status=0`；`publish_time` 空 |
| ZCZX-SZYWPX-UT-014 | Service | 新增并发布 | 单元测试 | JUnit5+Mockito | `saveAndPublish` | Mock Mapper | `insert`+发布逻辑 | `publish_status=1`；`publish_time` 非空 |
| ZCZX-SZYWPX-UT-015 | Service | 发布接口 | 单元测试 | JUnit5+Mockito | §3.6 | 未发布 id | `publish(id)` | `publish_status=1` |
| ZCZX-SZYWPX-UT-016 | Service | 下架保留发布日期 | 单元测试 | JUnit5+Mockito | §3.6 | 已发布、可下架 | `offline(id)` | `publish_status=0`；`publish_time` 仍保留 |
| ZCZX-SZYWPX-UT-017 | Service | 逻辑删除 | 单元测试 | JUnit5+Mockito | §3.7 | 未发布 | `remove` | `del_flag=2` |
| ZCZX-SZYWPX-UT-018 | Mapper | 筛选排序 | 单元测试 | JUnit5 | §3.7 | 无 | 检查 XML | `del_flag=0`；主题精确；`DATE(training_time)`；`training_time DESC` |

---

## 二、接口测试用例

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-SZYWPX-API-001 | 列表 | 默认分页排序 | 接口测试 | Postman | §5.2.2 | 已登录 | `GET .../list` | `rows`≤20；含 `enrollStatusName`；培训时间新在前 |
| ZCZX-SZYWPX-API-002 | 列表 | 培训主题精确 | 接口测试 | Postman | §2.5 | 有 T1 | `trainingTopic=牧业实战一期` | 仅 T1；主题片段不匹配 |
| ZCZX-SZYWPX-API-003 | 列表 | 培训日期区间 | 接口测试 | Postman | 闭区间 | 已知 `training_time` | `startDate`+`endDate` | 均在区间内 |
| ZCZX-SZYWPX-API-004 | 列表 | 培训日期非法 | 接口测试 | Postman | §8 | 已登录 | `startDate> endDate` | 失败 |
| ZCZX-SZYWPX-API-005 | 列表 | 不含已删除 | 接口测试 | Postman | 逻辑删除 | 已知 id 已删 | `GET list` | 无该 id |
| ZCZX-SZYWPX-API-006 | 新增 | 仅保存未发布 | 接口测试 | Postman | §5.1.2 | 已登录 | `POST` 合法 Body；`saveAndPublish=false` | 成功；`publishStatus=0` |
| ZCZX-SZYWPX-API-007 | 新增 | 保存并发布 | 接口测试 | Postman | §5.1.2 | 已登录 | `POST`+`saveAndPublish=true` | 成功；`publishStatus=1`；有 `publishTime` |
| ZCZX-SZYWPX-API-008 | 新增 | 时间链非法 | 接口测试 | Postman | §3.5 | 已登录 | `registrationEndTime≥trainingTime` | 失败 |
| ZCZX-SZYWPX-API-009 | 新增 | 计划人数非法 | 接口测试 | Postman | §3.5 | 已登录 | `plannedHeadCount=0` | 失败 |
| ZCZX-SZYWPX-API-010 | 新增 | 主题超长 | 接口测试 | Postman | 1～20 | 已登录 | 21 字主题 | 失败 |
| ZCZX-SZYWPX-API-011 | 详情 | 有效 id | 接口测试 | Postman | §5.5 | 已登录 | `GET /{id}` | 全字段+`enrollStatus`+`canOffline` |
| ZCZX-SZYWPX-API-012 | 详情 | 无效 id | 接口测试 | Postman | 异常 | 已登录 | 不存在/已删 id | 失败或空 `data` |
| ZCZX-SZYWPX-API-013 | 修改 | 未发布全字段 | 接口测试 | Postman | §5.3 | T1 未发布 | `PUT` 改地点/人数/时间链 | 成功 |
| ZCZX-SZYWPX-API-014 | 修改 | 已发布禁止 | 接口测试 | Postman | §5.3 | T3 已发布 | `PUT` | 失败；库不变 |
| ZCZX-SZYWPX-API-015 | 发布 | 列表发布 | 接口测试 | Postman | §5.6 | T1 未发布 | `POST .../publish/{id}` | `publishStatus=1` |
| ZCZX-SZYWPX-API-016 | 发布 | 重复发布 | 接口测试 | Postman | §5.6 | 已发布 id | 再次 `publish` | 失败 |
| ZCZX-SZYWPX-API-017 | 下架 | 报名前可下架 | 接口测试 | Postman | §5.6 | T2 已发布、报名未开始 | `POST .../offline/{id}` | `publishStatus=0`；`canOffline` 曾为 true |
| ZCZX-SZYWPX-API-018 | 下架 | 报名开始后禁止 | 接口测试 | Postman | §5.6 | T3 报名期内 | `POST .../offline/{id}` | 失败；提示报名已开始 |
| ZCZX-SZYWPX-API-019 | 删除 | 未发布删除 | 接口测试 | Postman | §5.4 | T1 | `DELETE /{id}` | 成功；列表无 |
| ZCZX-SZYWPX-API-020 | 删除 | 已发布禁止 | 接口测试 | Postman | §5.4 | T3 | `DELETE` | 失败 |
| ZCZX-SZYWPX-API-021 | 报名状态 | 报名中样本 | 接口测试 | Postman | §3.4 | T3 | `GET list` 找 T3 | `enrollStatus=2` |
| ZCZX-SZYWPX-API-022 | 报名状态 | 已报满样本 | 接口测试 | Postman | §3.4 | T4 | `GET list` 找 T4 | `enrollStatus=3` |
| ZCZX-SZYWPX-API-023 | 报名状态 | 已截止样本 | 接口测试 | Postman | §3.4 | T5 | `GET list` 找 T5 | `enrollStatus=4` |
| ZCZX-SZYWPX-API-024 | 端到端 | 增-发-下-改-发 | 接口测试 | Postman | §4 | 已登录 | `POST`保存→`publish`→`offline`→`PUT`→`publish` | 各步符合状态机 |
| ZCZX-SZYWPX-API-025 | 鉴权 | 未登录 | 接口测试 | curl | 安全 | 无 Token | `GET list` | 401 或统一未登录 |
| ZCZX-SZYWPX-API-026 | 权限 | 无发布权限 | 接口测试 | Postman | §6 | 无 publish | `POST .../publish/1` | 无权限失败 |
| ZCZX-SZYWPX-API-027 | 权限 | 无下架权限 | 接口测试 | Postman | §6 | 无 offline | `POST .../offline/2` | 无权限失败 |
| ZCZX-SZYWPX-API-028 | 响应 | 失败可读 | 接口测试 | Postman | §8 | 已登录 | 触发时间链、已发布修改、下架被拒 | `msg` 可区分 |
| ZCZX-SZYWPX-API-028 | 小程序 | 我的报名列表 | 接口测试 | Postman | 用户有有效报名 | `GET /app/practicalTraining/myEnroll/list` | 分页；仅本人已报名培训 |
| ZCZX-SZYWPX-API-028a | 小程序 | 我的报名详情 | 接口测试 | Postman | 已报名 T3 | `GET /app/practicalTraining/myEnroll/{id}` | 全字段；`canCancel` 与状态一致 |
| ZCZX-SZYWPX-API-029 | 小程序 | 立即报名 | 接口测试 | Postman | 报名中 | T3；未报名用户 | `POST /app/practicalTraining/{id}/enroll` | 成功；`actual_enrolled_count+1` |
| ZCZX-SZYWPX-API-030 | 小程序 | 取消报名 | 接口测试 | Postman | 报名中 | 已报名用户 | `POST .../cancelEnroll` | 成功；人数减 1 |
| ZCZX-SZYWPX-API-031 | 小程序 | 非报名中报名 | 接口测试 | Postman | T4 已满或 T5 截止 | 已登录 | `POST .../enroll` | 失败 |
| ZCZX-SZYWPX-API-032 | 小程序 | 已截止取消 | 接口测试 | Postman | T5 已截止且已报名 | `POST .../cancelEnroll` | 失败；提示已截止 |

---

## 三、界面测试用例（UI）

**测试工具**：**Playwright** + **Chromium**（`channel: 'chrome'` 使用本机 **Google Chrome**）。

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-SZYWPX-UI-001 | 列表 | 默认展示 | UI 测试 | Playwright+Chrome | §5.2.3 | 已登录；有数据 | 进入「实战业务培训」 | 含主题、培训时间、计划人数、地点、报名起止、发布日期、报名状态、实际报名、操作 |
| ZCZX-SZYWPX-UI-002 | 列表 | 主题精确筛选 | UI 测试 | Playwright+Chrome | §2.5 | 有 T1 | 输入全名「牧业实战一期」→搜索 | 仅 T1；输入片段无结果 |
| ZCZX-SZYWPX-UI-003 | 列表 | 培训日期筛选 | UI 测试 | Playwright+Chrome | §2.5 | 有样本 | 选培训日期区间→搜索 | 结果在闭区间内 |
| ZCZX-SZYWPX-UI-004 | 列表 | 重置 | UI 测试 | Playwright+Chrome | §5.2 | 已筛选 | 搜索→重置 | 条件清空 |
| ZCZX-SZYWPX-UI-005 | 列表 | 未发布操作列 | UI 测试 | Playwright+Chrome | §6 | 有未发布行 | 查看操作按钮 | 显示查看、发布、编辑、删除 |
| ZCZX-SZYWPX-UI-006 | 列表 | 已发布操作列 | UI 测试 | Playwright+Chrome | §6 | 有已发布且报名未开始行 | 查看操作 | 显示查看、下架；无编辑删除 |
| ZCZX-SZYWPX-UI-007 | 列表 | 报名开始后无下架 | UI 测试 | Playwright+Chrome | §5.6 | 报名已开始行 | 查看操作 | 无下架或禁用并提示 |
| ZCZX-SZYWPX-UI-008 | 新增 | 仅保存 | UI 测试 | Playwright+Chrome | §5.1.2 | 已登录 | 新增→填必填→点「确定」 | 成功；列表未发布；无发布日期 |
| ZCZX-SZYWPX-UI-009 | 新增 | 保存并发布 | UI 测试 | Playwright+Chrome | §5.1.2 | 已登录 | 新增→填必填→点「发布」 | 成功；列表已发布；有发布日期 |
| ZCZX-SZYWPX-UI-010 | 新增 | 培训时间默认 | UI 测试 | Playwright+Chrome | §5.1.1 | 打开新增 | 查看培训时间控件 | 默认当前时刻 |
| ZCZX-SZYWPX-UI-011 | 新增 | 时间链校验 | UI 测试 | Playwright+Chrome | §5.1.3 | 新增弹窗 | 报名截止≥培训时间→保存 | 校验失败 |
| ZCZX-SZYWPX-UI-012 | 新增 | 主题 20 字限制 | UI 测试 | Playwright+Chrome | §5.1.1 | 新增 | 输入超 20 字 | 无法输入或保存失败 |
| ZCZX-SZYWPX-UI-013 | 新增 | 封面上传 | UI 测试 | Playwright+Chrome | §5.1.1 | 有上传组件 | 上传 jpg≤10MB | 成功预览；超大/非图失败 |
| ZCZX-SZYWPX-UI-014 | 详情 | 只读完整 | UI 测试 | Playwright+Chrome | §5.5 | 任意行 | 点「查看」 | 字段只读；含报名状态 |
| ZCZX-SZYWPX-UI-015 | 编辑 | 未发布修改 | UI 测试 | Playwright+Chrome | §5.3 | 未发布行 | 编辑→改地点→保存 | 列表已更新 |
| ZCZX-SZYWPX-UI-016 | 编辑 | 已发布不可进 | UI 测试 | Playwright+Chrome | §5.3 | 已发布行 | 尝试编辑 | 无编辑入口或拒绝 |
| ZCZX-SZYWPX-UI-017 | 发布 | 行内发布 | UI 测试 | Playwright+Chrome | §5.6 | 未发布行 | 点「发布」→确认 | 变已发布；操作列变化 |
| ZCZX-SZYWPX-UI-018 | 下架 | 报名前下架 | UI 测试 | Playwright+Chrome | §5.6 | 已发布、报名未开始 | 点「下架」→确认 | 变未发布；可再编辑 |
| ZCZX-SZYWPX-UI-019 | 下架 | 报名开始后 | UI 测试 | Playwright+Chrome | §5.6 | 报名已开始 | 无下架或点击提示 | 与 API-018 一致 |
| ZCZX-SZYWPX-UI-020 | 删除 | 确认删除 | UI 测试 | Playwright+Chrome | §5.4 | 未发布行 | 删除→确认 | 行消失 |
| ZCZX-SZYWPX-UI-021 | 删除 | 取消删除 | UI 测试 | Playwright+Chrome | §5.4 | 未发布行 | 删除→取消 | 行仍在 |
| ZCZX-SZYWPX-UI-022 | 报名状态 | 标签展示 | UI 测试 | Playwright+Chrome | §2.3 | 含 T3/T4/T5 | 查看列表报名状态列 | 分别见报名中/已报满/已截止（或对应样本） |
| ZCZX-SZYWPX-UI-023 | 端到端 | 全流程 | UI 集成 | Playwright+Chrome | §4 | 权限齐备 | 新增保存→发布→查看→下架→编辑→再发布→删除 | 无报错；状态与按钮符合矩阵 |
| ZCZX-SZYWPX-UI-024 | 权限 | 只读角色 | UI 测试 | Playwright+Chrome | §6 | 无写权限 | 进入模块 | 无新增/编辑/删除/发布/下架 |
| ZCZX-SZYWPX-UI-025 | 列表 | 日期区间非法 | UI 测试 | Playwright+Chrome | §8 | 已登录 | 培训日期起晚于止→搜索 | 提示；不查或空 |

---

## Playwright 与谷歌浏览器（实施提示）

- 安装：`npm i -D @playwright/test`；`npx playwright install chrome`。  
- 配置：`use: { channel: 'chrome', locale: 'zh-CN', baseURL: 'http://localhost:80' }`；`storageState` 复用登录态。  
- 路由：`page.goto('/techService/practicalTraining')`（以菜单 `component` 为准）。  
- 新增：`page.getByRole('button', { name: '新增' })`；弹窗内 `page.getByLabel('培训主题').fill('…')`；`page.getByRole('button', { name: '发布' })` / `{ name: '确定' }`。  
- 日期：`type="daterange"` 的培训日期、datetime 的报名/培训时间按项目选择器定位。  
- 下架：断言报名已开始行 `getByRole('button', { name: '下架' })` 不可见或 disabled。

---

## 覆盖对照

| 类别 | 单元 UT | 接口 API | 界面 UI |
| --- | --- | --- | --- |
| 正常流程 | UT-013～016、018 | API-001～007、011、013、015、017、021～024 | UI-001～010、014～018、023 |
| 异常流程 | UT-001～006、010、012 | API-004、008～010、012、014、016、018～020 | UI-011～013、019～021、025 |
| 业务约束 | UT-001～005、010～012 | API-002、008～010、014、016～018 | UI-002、005～007、012、016、019 |
| 时间链 | UT-001 | API-008 | UI-011 |
| 报名状态 | UT-007～009 | API-021～023 | UI-022 |
| 发布/下架 | UT-010～016 | API-006～007、015～018 | UI-008～009、017～019 |
| 权限/鉴权 | — | API-025～027 | UI-024 |

---

## 功能需求追溯（自查）

| 需求章节 | 要点 | 主要对应用例 |
| --- | --- | --- |
| §5.1 新增 | 字段、默认时间、确定/发布 | UT-001～005、013～014；API-006～010；UI-008～013 |
| §5.2 列表 | 精确主题、日期区间、列展示 | API-001～004；UI-001～004、022 |
| §5.3 修改 | 仅未发布 | UT-010；API-013～014；UI-015～016 |
| §5.4 删除 | 逻辑删除 | UT-017；API-019～020；UI-020～021 |
| §5.5 查看 | 只读 | API-011；UI-014 |
| §5.6 发布/下架 | 下架前置 | UT-011～012、016；API-015～018；UI-017～019 |
| §2.3 报名状态 | 四档计算 | UT-007～009；API-021～023；UI-022 |
| §6 权限 | 按钮级 | API-025～027；UI-024 |

---

## 修订记录

| 版本 | 说明 |
| --- | --- |
| 1.0 | 初版：单元 18、接口 28、UI 25；覆盖 CRUD、发布下架、报名状态、时间链；Playwright+Chrome；编号前缀 **ZCZX-SZYWPX** |
| 1.1 | 增补 UT-010：修改未发布时 `training_status` 非空回填 |
