# 休药期标准管理 — 测试用例 > 依据:`休药期标准管理功能需求.md`、`休药期标准管理技术方案.md` > **接口 Base Path**:`/breedingStandards/diseaseTreatment/withdrawalPeriod`;若含 `context-path` 或网关前缀须补齐。鉴权与若依一致(Cookie / Token)。 > **权限标识(建议)**:`withdrawalPeriod:standard:list|query|add|edit|remove|syncKb|removeKb`(**无** publish / offline)。 **通用前置(无特殊说明)**:具备本模块菜单与按钮权限的账号已登录;测试环境可访问知识库或已按技术方案启用占位(如 `LOCAL-{id}`)。**药物名称**:必填,**1~20** 字符(计数口径与项目全局一致);**全表唯一**(trim 后精确匹配)。**药物类型**:`1`抗生素 `2`抗原虫 `3`抗病毒 `4`激素。**休药期**:整数 **1~999** 天。**使用指南 / 药物作用**:必填,各 **1~200** 汉字(计数口径与项目全局一致)。**知识库同步状态**:`0` 未同步 / `1` 已同步;本模块**不设发布/下架**。 **界面(UI)测试**:借助 **Playwright** 启动 **Chromium**(与 **Google Chrome 同源内核**);可配置 `channel: 'chrome'` 调用本机已安装的谷歌浏览器,模拟点击、输入与断言。 --- ## 一、单元测试用例 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | XYP-BZ-UT-001 | 枚举/持久化 | `kb_sync_status` 合法值 | 单元测试 | JUnit5 | 仅两种稳态 | 无 | 校验/映射仅允许 `0`、`1`;写入 `2`、`-1`、`null`(若可) | 拒绝非法值;合法 `0`/`1` 可落库 | | XYP-BZ-UT-002 | 状态守卫 | 编辑前置 | 单元测试 | JUnit5 | 需求 **4.3** / 矩阵 | 无 | `canEdit(kb=0)` true;`canEdit(kb=1)` false | 与 **§5**「已同步不可改」一致 | | XYP-BZ-UT-003 | 状态守卫 | 删除前置 | 单元测试 | JUnit5 | 需求 **4.4** | 无 | `canDelete(kb=0)` true;`canDelete(kb=1)` false | 已同步须先移出 | | XYP-BZ-UT-004 | 状态守卫 | 同步知识库前置 | 单元测试 | JUnit5 | 需求 **4.5** / 矩阵 | 无 | `canSyncKb(kb=0)` true;`canSyncKb(kb=1)` false | 仅未同步可同步 | | XYP-BZ-UT-005 | 状态守卫 | 移出知识库前置 | 单元测试 | JUnit5 | 需求 **4.6** / 矩阵 | 无 | `canRemoveKb(kb=1)` true;`canRemoveKb(kb=0)` false | 仅已同步可移出 | | XYP-BZ-UT-006 | 参数校验 | 药物名称长度 | 单元测试 | JUnit5 | 需求 **4.1** | 无 | 空串、1 字、20 字、21 字调用校验/Bean 校验 | 空/21 失败;1~20 通过 | | XYP-BZ-UT-007 | 参数校验 | 药物类型枚举 | 单元测试 | JUnit5 | 技术方案 **§2.2** | 无 | `drugType ∈ {1,2,3,4}` 通过;`0`、`5`、`null` 失败 | 与四类一致 | | XYP-BZ-UT-008 | 参数校验 | 休药期天数边界 | 单元测试 | JUnit5 | 需求 **4.1** | 无 | `0`、`1`、`999`、`1000`、非整数(若可输入) | `1~999` 通过;其余失败 | | XYP-BZ-UT-009 | 参数校验 | 使用指南/药物作用字数 | 单元测试 | JUnit5 | 需求 **4.1** | 无 | 各:空、1 汉字、200 汉字、201 汉字 | 空/超上限失败;合法区间通过 | | XYP-BZ-UT-010 | Service | 新增落库状态 | 单元测试 | JUnit5+Mockito | 需求 **4.1** | Mock Mapper 成功 | `add(合法 DTO)` | `kb_sync_status=0`;`kb_doc_id` 为空或 null | | XYP-BZ-UT-011 | Service | 修改—已同步拒绝 | 单元测试 | JUnit5+Mockito | 需求 **2.2**、**4.3** | 库中记录 `kb=1` | `update(...)` | 业务失败;不写业务字段 | | XYP-BZ-UT-012 | Service | 修改—未同步不调知识库 | 单元测试 | JUnit5+Mockito | 需求 **2.2**(禁止已同步下推库) | `kb=0`;Spy KB 客户端 | `update` 成功路径 | **未调用**知识库「更新/推送」类接口 | | XYP-BZ-UT-013 | Service | 同步成功 | 单元测试 | JUnit5+Mockito | 需求 **4.5** | `kb=0`;Mock KB 返回 `docId` | `syncKb(id)` | `kb=1`;`kb_doc_id` 非空(或占位 `LOCAL-{id}`) | | XYP-BZ-UT-014 | Service | 同步失败不翻转 | 单元测试 | JUnit5+Mockito | 需求 **4.5** | `kb=0`;Mock KB 抛错/失败码 | `syncKb(id)` | 仍为 `kb=0`;`kb_doc_id` 不变 | | XYP-BZ-UT-015 | Service | 移出成功 | 单元测试 | JUnit5+Mockito | 需求 **4.6** | `kb=1`;Mock KB 成功 | `removeKb(id)` | `kb=0`;`kb_doc_id` 清空 | | XYP-BZ-UT-016 | Service | 移出失败保持已同步 | 单元测试 | JUnit5+Mockito | 需求 **4.6** | `kb=1`;Mock KB 失败 | `removeKb(id)` | 仍为 `kb=1`;`kb_doc_id` 保留 | | XYP-BZ-UT-017 | Service | 删除—未同步联动幂等删库 | 单元测试 | JUnit5+Mockito | 需求 **4.4** | `kb=0`;Mock KB | `remove(ids)` | 本地记录删除;Mock 验证发起知识库**幂等删除**(若实现为「KB 删除失败则阻断本地删」,须另补专项用例覆盖该策略) | | XYP-BZ-UT-018 | Service | 删除—已同步拒绝 | 单元测试 | JUnit5+Mockito | 需求 **4.4** | `kb=1` | `remove(ids)` | 失败;记录仍在 | | XYP-BZ-UT-019 | Mapper/XML(可选) | 列表 keyword 仅 drug_name | 单元测试 | MyBatis `@Test` 或集成 | 需求 **4.2**、技术方案 **3.1** | 库内造数:名称不含「甲」、使用指南含「甲」 | `list` 带 `keyword=甲` | 该条**不**出现在结果(若仅名称模糊) | --- ## 二、接口测试用例 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | XYP-BZ-API-001 | 列表 | 默认分页与排序 | 接口测试 | Postman/curl/MockMvc | 需求 **4.2** | 已登录;有多条 | `GET /withdrawalPeriod/standard/list` | `rows` 条数≤默认(如 20);`create_time` 新在前(与技术方案建议一致) | | XYP-BZ-API-002 | 列表 | 药物名称模糊 | 接口测试 | Postman | 需求 **4.2** | 已登录 | `keyword=` 仅命中 `drug_name` 子串 | 返回含预期行;**不**应仅靠 `usage_guide`/`drug_effect` 命中(与 **3.1** 一致) | | XYP-BZ-API-003 | 列表 | 药物类型精确筛选 | 接口测试 | Postman | 需求 **4.2** | 已登录 | `drugType=1`(可空不传测全集) | 返回行 `drugType` 均为 1 | | XYP-BZ-API-004 | 列表 | 关键字+类型组合 | 接口测试 | Postman | 组合查询 | 已登录 | 同时传 `keyword`、`drugType` | 同时满足 | | XYP-BZ-API-005 | 列表 | 展示同步状态 | 接口测试 | Postman | 需求 **4.2** | 已登录;有 0/1 各一条 | `GET .../list` | 每行含 `kbSyncStatus`(或等价字段名与前端一致) | | XYP-BZ-API-006 | 新增 | 合法提交 | 接口测试 | Postman/Swagger/MockMvc | 正常主流程 | 已登录 | `POST /withdrawalPeriod/standard` Body:`drugName`、`drugType`、`withdrawalDays`、`usageGuide`、`drugEffect` 均合法 | `code` 成功;库中 `kb_sync_status=0` | | XYP-BZ-API-007 | 新增 | 名称非法 | 接口测试 | Postman | 需求 **4.1** | 已登录 | 名称空或 21 字或缺字段 | 失败;无新记录 | | XYP-BZ-API-007a | 新增 | 名称重复 | 接口测试 | Postman | 需求 **4.1** 唯一 | 已存在 `drugName=药A` | `POST` 再提交 `drugName=药A` | 失败;`msg` 含「药物名称已存在」 | | XYP-BZ-API-008 | 新增 | 类型/休药期非法 | 接口测试 | Postman | 需求 **4.1** | 已登录 | `drugType=0` 或 `withdrawalDays=0`/`1000` | 失败 | | XYP-BZ-API-009 | 新增 | 使用指南/药物作用超长 | 接口测试 | Postman | 需求 **4.1** | 已登录 | 任一项 >200 汉字(按项目计数) | 失败;可读 `msg` | | XYP-BZ-API-010 | 详情 | 有效 id | 接口测试 | Postman | 需求 **4.7** | 已登录 | `GET /withdrawalPeriod/standard/{id}` | 含 **4.1** 全部业务字段 + 同步状态(及 `kbDocId` 若已同步) | | XYP-BZ-API-011 | 详情 | 无效 id | 接口测试 | Postman | 异常 | 已登录 | 不存在 id | 404 或业务失败;与项目约定一致 | | XYP-BZ-API-012 | 修改 | 未同步成功 | 接口测试 | Postman | 需求 **4.3** | 已登录;目标 `kb=0` | `PUT /withdrawalPeriod/standard` Body 含 `id` 与合法字段 | 成功;仍为 `kb=0`(除非另调同步) | | XYP-BZ-API-013 | 修改 | 已同步拒绝 | 接口测试 | Postman | 需求 **4.3**、矩阵 | 已登录;目标 `kb=1` | `PUT ...` 改任意业务字段 | 失败;数据不变 | | XYP-BZ-API-013a | 修改 | 名称重复 | 接口测试 | Postman | 需求 **4.3** 唯一 | 已登录;A/B 两条未同步;改 B 的 `drugName` 为 A 的名称 | `PUT` | 失败;提示「药物名称已存在」 | | XYP-BZ-API-014 | 删除 | 未同步成功 | 接口测试 | Postman | 需求 **4.4** | 已登录;`kb=0` | `DELETE /withdrawalPeriod/standard/{ids}` | 成功;记录消失;对端收到幂等删除(或按项目固定策略) | | XYP-BZ-API-015 | 删除 | 已同步拒绝 | 接口测试 | Postman | 需求 **4.4** | 已登录;`kb=1` | `DELETE ...` | 失败;提示先移出 | | XYP-BZ-API-016 | 删除 | 批量 ids | 接口测试 | Postman | 技术方案 **3.5** | 已登录;多条 `kb=0` | `DELETE .../1,2,3`(若依惯例逗号分隔) | 全部删除成功或部分失败规则与项目一致 | | XYP-BZ-API-017 | 同步知识库 | 未同步成功 | 接口测试 | Postman | 需求 **4.5** | 已登录;`kb=0` | `POST /withdrawalPeriod/standard/syncKb/{id}` | `kb=1`;`kb_doc_id` 有值 | | XYP-BZ-API-018 | 同步知识库 | 已同步重复调用 | 接口测试 | Postman | 矩阵 **§5** | 已登录;`kb=1` | `POST .../syncKb/{id}` | 失败;仍为已同步 | | XYP-BZ-API-019 | 同步知识库 | 失败可重试 | 接口测试 | Postman+Mock 对端 | 需求 **4.5** | KB 不可用或返回失败;`kb=0` | `POST .../syncKb/{id}` | 仍为未同步;`msg` 可读 | | XYP-BZ-API-020 | 移出知识库 | 已同步成功 | 接口测试 | Postman | 需求 **4.6** | 已登录;`kb=1` | `POST /withdrawalPeriod/standard/removeKb/{id}` | `kb=0`;`kb_doc_id` 空 | | XYP-BZ-API-021 | 移出知识库 | 未同步调用 | 接口测试 | Postman | 矩阵 | 已登录;`kb=0` | `POST .../removeKb/{id}` | 失败 | | XYP-BZ-API-022 | 移出知识库 | 失败保持已同步 | 接口测试 | Postman | 需求 **4.6** | Mock KB 失败;`kb=1` | `POST .../removeKb/{id}` | 仍为已同步 | | XYP-BZ-API-023 | 关键路径 | 移出→改→再同步 | 接口测试 | Postman | 需求 **3.3** | 一条 `kb=1` | 顺序:`removeKb` 成功 → `PUT` 改名称 → `syncKb` 成功 | 最终 `kb=1`;知识库内容与最新业务一致 | | XYP-BZ-API-024 | 鉴权 | 未登录 | 接口测试 | curl | 安全 | 无 Token/Cookie | `GET .../list` | 401 或重定向登录 | | XYP-BZ-API-025 | 权限 | 无对应按钮权限 | 接口测试 | Postman | 需求 **§7** | 仅 `list` 无 `add` | `POST /withdrawalPeriod/standard` | 无权限失败 | | XYP-BZ-API-026 | 错误提示 | 校验与 KB 失败可读 | 接口测试 | Postman | 需求 **§6** | 已登录 | 触发校验失败、同步失败 | `msg` 区分输入不合法与知识库不可用(若项目有约定码) | --- ## 三、界面测试用例(UI) **测试工具**:**Playwright** + **Chromium**(`channel: 'chrome'` 时使用本机 **Google Chrome**)。步骤与脚本映射:`page.goto`、`locator.fill`、`locator.click`、`expect`;删除/同步/移出等二次确认:`page.once('dialog')` 或页面内「确定」按钮。 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | XYP-BZ-UI-001 | 列表 | 默认分页与排序 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.2** | 已登录;数据>默认页大小 | 进入休药期标准列表页 | 每页条数与项目一致;创建时间新在前 | | XYP-BZ-UI-002 | 列表 | 药物名称关键字 | UI 测试 | Playwright+Chrome/Chromium | 名称模糊 | 存在名称含关键词记录 | 输入关键字→查询 | 表格含该行 | | XYP-BZ-UI-003 | 列表 | 关键字不匹配「仅指南含词」 | UI 测试 | Playwright+Chrome/Chromium | 与 **4.2**/技术方案「仅 drug_name」 | 造数:名称不含「测」、使用指南含「测」 | 关键字填「测」→查询 | **不**出现该行(验证未对指南模糊) | | XYP-BZ-UI-004 | 列表 | 药物类型筛选 | UI 测试 | Playwright+Chrome/Chromium | 精确筛选 | 多条不同类型 | 选某一类型→查询 | 类型列均为所选 | | XYP-BZ-UI-005 | 列表 | 组合与重置 | UI 测试 | Playwright+Chrome/Chromium | 恢复条件 | 已筛选 | 关键字+类型→查询→重置 | 恢复默认列表 | | XYP-BZ-UI-006 | 列表 | 同步状态列与操作矩阵 | UI 测试 | Playwright+Chrome/Chromium | 需求 **§5** | 准备未同步、已同步各一条 | 逐行查看操作按钮/菜单 | **未同步**:可查、改、删、同步;**无**移出。**已同步**:可查、移出;**无**改、删、同步 | | XYP-BZ-UI-007 | 新增 | 完整合法主流程 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.1**、**3.1** | 已登录;有新增权限 | 新增→填名称(1~20)、类型、休药期、使用指南、药物作用→提交 | 成功提示;列表出现;状态为**未同步** | | XYP-BZ-UI-008 | 新增 | 边界与必填校验 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.1**、**§6** | 已登录 | 分别测:名称空/21 字;休药期 0/1000;指南或作用空/超长;类型未选 | 对应字段校验失败;无脏数据落库 | | XYP-BZ-UI-009 | 详情 | 字段与同步状态展示 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.7** | 已有一条记录 | 点详情/查看 | 展示 **4.1** 全部字段 + 未同步/已同步 | | XYP-BZ-UI-010 | 详情 | 已同步只读 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.7** | 已同步记录 | 打开详情 | 无保存式编辑或编辑入口不可用 | | XYP-BZ-UI-011 | 详情 | 未同步可进编辑 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.7** | 未同步记录 | 详情→编辑(或列表编辑) | 可修改并保存 | | XYP-BZ-UI-012 | 修改 | 未同步保存成功 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.3** | 未同步样本 | 改名称或休药期→保存 | 成功;仍为**未同步** | | XYP-BZ-UI-013 | 修改 | 已同步不可改 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.3**、矩阵 | 已同步样本 | 尝试从列表/详情进入编辑 | 无编辑或保存被拒绝 | | XYP-BZ-UI-014 | 知识库 | 同步成功 | UI 集成 | Playwright+Chrome/Chromium | 需求 **4.5** | 未同步记录 | 点「同步知识库」→确认(若有) | 状态变为**已同步**;可复查详情 `kbDocId`(若 UI 展示) | | XYP-BZ-UI-015 | 知识库 | 已同步无「同步」入口 | UI 测试 | Playwright+Chrome/Chromium | 矩阵 | 已同步行 | 查看操作区 | 「同步」隐藏或禁用 | | XYP-BZ-UI-016 | 知识库 | 同步失败提示与可重试 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.5**、**§6** | 未同步;KB 失败环境或 Mock | 点同步 | 明确失败文案;仍为未同步;可再次点击 | | XYP-BZ-UI-017 | 知识库 | 移出成功 | UI 集成 | Playwright+Chrome/Chromium | 需求 **4.6** | 已同步记录 | 点「移出知识库」→确认 | 变为**未同步**;可再编辑 | | XYP-BZ-UI-018 | 知识库 | 未同步无「移出」 | UI 测试 | Playwright+Chrome/Chromium | 矩阵 | 未同步行 | 查看操作区 | 「移出」隐藏或禁用 | | XYP-BZ-UI-019 | 知识库 | 移出失败提示 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.6** | 已同步;KB 移出失败 | 点移出 | 仍为已同步;可读错误提示 | | XYP-BZ-UI-020 | 删除 | 未同步删除 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.4** | 未同步记录 | 删除→二次确认确定 | 记录从列表消失 | | XYP-BZ-UI-021 | 删除 | 已同步不可删 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.4** | 已同步记录 | 尝试删除 | 无删除或操作失败并提示先移出 | | XYP-BZ-UI-022 | 删除 | 取消确认不删 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.4** 交互 | 未同步 | 删除→点取消 | 记录仍在 | | XYP-BZ-UI-023 | 端到端 | 状态机全链路 | UI 集成 | Playwright+Chrome/Chromium | 需求 **3.3** | 可新建 | 新增(未同步)→同步(已同步)→详情只读→移出(未同步)→编辑保存→再同步(已同步)→移出→删除 | 每步状态与矩阵一致;最终记录删除成功 | | XYP-BZ-UI-024 | 权限 | 只读/无写权限账号 | UI 测试 | Playwright+Chrome/Chromium | 需求 **§7** | 无 `add`/`edit` 等 | 登录进入模块 | 无新增/编辑/删除或按钮不可见;列表可查(若有 `list`) | | XYP-BZ-UI-025 | 回归 | 无发布/下架入口 | UI 测试 | Playwright+Chrome/Chromium | 需求 **§1 边界** | 任意状态记录 | 扫页面按钮与路由 | **无**「发布」「下架」类操作 | --- ## 四、用例与需求/设计追溯(摘要) | 需求章节 | 单元测试 | 接口测试 | UI 测试 | | --- | --- | --- | --- | | **4.1** 新增字段与规则 | UT-006~010 | API-006~009 | UI-007、UI-008 | | **4.2** 列表 | UT-019 | API-001~005 | UI-001~005 | | **4.3** 修改 | UT-002、011、012 | API-012、013 | UI-012、013 | | **4.4** 删除与幂等通知 | UT-003、017、018 | API-014~016 | UI-020~022 | | **4.5** 同步 | UT-004、013、014 | API-017~019 | UI-014~016 | | **4.6** 移出 | UT-005、015、016 | API-020~022 | UI-017~019 | | **4.7** 详情 | — | API-010、011 | UI-009~011 | | **§5** 矩阵 | UT-002~005 | API-013、015、018、021 | UI-006、013、015、018、021 | | **§6** 错误提示 | UT-009 | API-026 | UI-008、016、019 | | **3.3** 关键路径 | — | API-023 | UI-023 | --- ## 五、Playwright 脚本提示(可选落地) ```typescript // 示例:使用本机 Chrome(需已安装);无则去掉 channel 使用内置 Chromium import { test, expect } from '@playwright/test'; test.use({ channel: 'chrome', headless: true }); test('XYP-BZ-UI-023 摘要:新增→同步→移出→改→再同步→删', async ({ page }) => { // 1. 登录(URL/账号按环境配置) await page.goto(process.env.BASE_URL + '/login'); await page.getByPlaceholder('用户名').fill(process.env.USER!); await page.getByPlaceholder('密码').fill(process.env.PASS!); await page.getByRole('button', { name: /登录/ }).click(); // 2. 进入「休药期标准」菜单(菜单文案以实际为准) await page.getByText('休药期标准', { exact: false }).click(); // 3. 新增、同步、移出、编辑、再同步、删除… 使用 getByRole/getByLabel 定位表单与按钮 // 4. expect(locator).toContainText('未同步'|'已同步') 等断言 }); ``` **说明**:具体菜单路径、表单 `label`、按钮文案以若依前端实现为准;建议将 `BASE_URL`、登录信息与「同步/移出」确认框选择器抽为环境变量或 Page Object,便于 CI 与多环境复用。