# 药物禁配标准管理 — 测试用例 > 依据:`药物禁配标准管理功能需求.md`、`药物禁配标准管理技术方案.md` > **接口 Base Path**:`/breedingStandards/diseaseTreatment/drugIncompatibility`;若含 `context-path` 或网关前缀须补齐。鉴权与若依一致(Cookie / Token)。 > **权限标识(建议)**:`drugIncompatibility:standard:list|query|add|edit|remove|syncKb|removeKb`(**无** publish / offline)。 **通用前置(无特殊说明)**:具备本模块菜单与按钮权限的账号已登录;测试环境可访问知识库或已按技术方案启用占位(如 `LOCAL-{id}`)。**主药名称**:必填,**1~20** 字符(计数口径与项目全局一致);**允许重复**。**配伍药物**:至少 **1** 条;每条名称 **1~20** 字符;trim 后**互不相同**且**均不等于主药**;顺序与保存一致。**配伍结果**:选填,**≤50** 字符。**知识库同步状态**:`0` 未同步 / `1` 已同步;本模块**不设发布/下架**。列表默认 **keyword 仅匹配主药名**(不匹配配伍名,除非需求已扩展并验收)。 **知识库说明**:后端当前可为**占位**实现(同步即成功写 `LOCAL-{id}`)。含「知识库调用失败」的用例在占位阶段可标为 **待 HTTP 对接后执行**;或通过对 Service 编排层 Mock 失败路径单独补测。 **界面(UI)测试**:借助 **Playwright** 启动 **Chromium**(与 **Google Chrome 同源内核**);可配置 `channel: 'chrome'` 调用本机已安装的谷歌浏览器,模拟点击、输入与断言。前端菜单路由以实际若依页面为准(未上线页面时步骤中菜单名写为**占位**,落地后替换)。 --- ## 一、单元测试用例 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | JP-BZ-UT-001 | 枚举/持久化 | `kb_sync_status` 合法值 | 单元测试 | JUnit5 | 仅两种稳态 | 无 | 校验/映射仅允许 `0`、`1`;拒绝 `2`、`-1` 等 | 非法值拒绝;`0`/`1` 合法 | | JP-BZ-UT-002 | 状态守卫 | 编辑前置 | 单元测试 | JUnit5 | 需求 **4.3**、操作矩阵 | 无 | `canEdit(kb=0)` true;`canEdit(kb=1)` false | 已同步不可改 | | JP-BZ-UT-003 | 状态守卫 | 删除前置 | 单元测试 | JUnit5 | 需求 **4.4** | 无 | `canDelete(kb=0)` true;`canDelete(kb=1)` false | 已同步须先移出 | | JP-BZ-UT-004 | 状态守卫 | 同步知识库前置 | 单元测试 | JUnit5 | 需求 **4.5**、矩阵 | 无 | `canSyncKb(kb=0)` true;`canSyncKb(kb=1)` false | 仅未同步可同步 | | JP-BZ-UT-005 | 状态守卫 | 移出知识库前置 | 单元测试 | JUnit5 | 需求 **4.6**、矩阵 | 无 | `canRemoveKb(kb=1)` true;`canRemoveKb(kb=0)` false | 仅已同步可移出 | | JP-BZ-UT-006 | 参数校验 | 主药名称长度 | 单元测试 | JUnit5 | 需求 **4.1** | 无 | 空串、21 字、`validateMainDrugName`;合法 1~20 字 | 空/超长失败;合法通过 | | JP-BZ-UT-007 | 参数校验 | 配伍结果长度 | 单元测试 | JUnit5 | 需求 **4.1** | 无 | `null`、全空白、50 字、51 字 | `null`/空白/50 通过;51 失败 | | JP-BZ-UT-008 | 参数校验 | 配伍列表至少一条 | 单元测试 | JUnit5 | 需求 **2.3**、**4.1** | `companions=[]` | `validateCompanions` | 抛错(至少一条) | | JP-BZ-UT-009 | 参数校验 | 配伍名同条重复 | 单元测试 | JUnit5 | 需求 **2.3** | 两条配伍 trim 后同名 | `validateCompanions` | 抛错(不能重复) | | JP-BZ-UT-010 | 参数校验 | 配伍名与主药相同 | 单元测试 | JUnit5 | 需求 **2.3** | 配伍名与主药 trim 后相同 | `validateCompanions` | 抛错(不能与主药相同) | | JP-BZ-UT-011 | 参数校验 | `trimFieldsForSave` | 单元测试 | JUnit5 | 需求 **2.3** 名称口径 | 主药/配伍含首尾空格;配伍结果为空白串 | `trimFieldsForSave` 后再校验 | 主药、配伍 trim 正确;空配伍结果变 `null` | | JP-BZ-UT-012 | Service | 新增落库与子表 | 单元测试 | JUnit5+Mockito | 需求 **4.1** | Mock 主表 insert 回填 id;Mock 子表 insert | `insertBizDrugIncompatibilityStandard(合法体)` | `kb_sync_status=0`;子表 insert 被调用 | | JP-BZ-UT-013 | Service | 修改—已同步拒绝 | 单元测试 | JUnit5+Mockito | 需求 **2.2**、**4.3** | 库中 `kb=1` | `updateBizDrugIncompatibilityStandard` | 业务失败;不写主表 update | | JP-BZ-UT-014 | Service | 修改—未同步替换子表 | 单元测试 | JUnit5+Mockito | 技术方案一致性 | `kb=0`;Mock update/delete/insert | `update` 成功路径 | 先 `deleteByStandardId` 再批量 insert;`kb` 不被客户端篡改 | | JP-BZ-UT-015 | Service | 修改—主键为空 | 单元测试 | JUnit5+Mockito | 异常流程 | `id=null` | `update` | 抛错(主键不能为空) | | JP-BZ-UT-016 | Service | 同步成功(占位) | 单元测试 | JUnit5+Mockito | 需求 **4.5** | `kb=0`;Mock update | `syncKb(id)` | `kb=1`;`kb_doc_id` 含 `LOCAL-{id}` 或非空 | | JP-BZ-UT-017 | Service | 同步—已同步拒绝 | 单元测试 | JUnit5+Mockito | 需求 **4.5** 互斥 | `kb=1` | `syncKb` | 抛错;不更新为成功态 | | JP-BZ-UT-018 | Service | 移出成功 | 单元测试 | JUnit5+Mockito | 需求 **4.6** | `kb=1`;Mock update | `removeKb(id)` | `kb=0`;`kb_doc_id` 清空 | | JP-BZ-UT-019 | Service | 移出—未同步拒绝 | 单元测试 | JUnit5+Mockito | 矩阵互斥 | `kb=0` | `removeKb` | 抛错 | | JP-BZ-UT-020 | Service | 删除—已同步拒绝 | 单元测试 | JUnit5+Mockito | 需求 **4.4** | `kb=1` | `deleteBizDrugIncompatibilityStandardByIds` | 抛错;不执行主表 delete | | JP-BZ-UT-021 | Service | 删除—批量含已同步整单失败 | 单元测试 | JUnit5+Mockito | 需求 **4.4** 批量 | ids 含未同步+已同步 | `delete...ByIds` | 抛错;主表 delete 不调用 | | JP-BZ-UT-022 | Service | 删除—未同步成功 | 单元测试 | JUnit5+Mockito | 需求 **4.4** | 全部 `kb=0` | `delete...ByIds` | 主表 delete 调用(子表级联由库保证) | | JP-BZ-UT-023 | Service | 详情带子表顺序 | 单元测试 | JUnit5+Mockito | 需求 **4.7** | Mock 主表+多行子表 | `selectBizDrugIncompatibilityStandardById` | `companions` 条数与顺序与 Mapper 一致 | | JP-BZ-UT-024 | Mapper/XML(可选) | 列表 keyword 仅主药 | 单元测试 | MyBatis 集成或手工 SQL | 需求 **4.2**、技术方案 **3.1** | 造数:主药不含「甲」、配伍名含「甲」 | `list` 带 `keyword=甲` | 该条**不**命中(默认仅主药模糊) | --- ## 二、接口测试用例 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | JP-BZ-API-001 | 列表 | 默认分页与排序 | 接口测试 | Postman/curl/MockMvc | 需求 **4.2** | 已登录;有多条 | `GET /drugIncompatibility/standard/list?pageNum=1&pageSize=10` | `rows`/`total` 正常;默认创建时间新在前(与技术方案一致) | | JP-BZ-API-002 | 列表 | 主药名称模糊 | 接口测试 | Postman | 需求 **4.2** | 已登录 | `keyword=` 仅命中 `main_drug_name` 子串 | 返回含预期行 | | JP-BZ-API-003 | 列表 | 关键字不匹配「仅配伍含词」 | 接口测试 | Postman | 需求 **4.2**、**1.2** | 主药不含「测」、配伍名含「测」 | `keyword=测` | **不**出现该行 | | JP-BZ-API-004 | 列表 | 展示同步状态与配伍条数 | 接口测试 | Postman | 需求 **4.2** | 已登录;有 0/1 状态数据 | `GET .../list` | 行内含 `kbSyncStatus`、`companionCount`(字段名与前端一致即可) | | JP-BZ-API-005 | 新增 | 合法提交(含多配伍) | 接口测试 | Postman/MockMvc | 正常主流程 **4.1** | 已登录;`add` 权限 | `POST /drugIncompatibility/standard` Body:`mainDrugName`、`compatResult` 可空、`companions`≥1 | `code` 成功;库中 `kb_sync_status=0`;子表条数一致 | | JP-BZ-API-006 | 新增 | 主药非法 | 接口测试 | Postman | 需求 **4.1** | 已登录 | 主药空或 21 字或缺主药 | 失败;无新主表行 | | JP-BZ-API-006a | 新增 | 主药名称可重复 | 接口测试 | Postman | 需求 **4.1** | 已存在 `mainDrugName=主药A` | `POST` 再提交同名(配伍不同) | 成功;两条主药名相同记录并存 | | JP-BZ-API-007 | 新增 | 配伍条数/重复/同主药 | 接口测试 | Postman | 需求 **2.3**、**4.1** | 已登录 | `companions` 空数组;或两配伍同名;或配伍=主药 | 失败;可读 `msg` | | JP-BZ-API-008 | 新增 | 配伍结果超长 | 接口测试 | Postman | 需求 **4.1** | 已登录 | `compatResult` 长度 51 | 失败 | | JP-BZ-API-009 | 详情 | 有效 id | 接口测试 | Postman | 需求 **4.7** | 已登录 | `GET /drugIncompatibility/standard/{id}` | 含主药、有序 `companions`、配伍结果、同步状态 | | JP-BZ-API-010 | 详情 | 无效 id | 接口测试 | Postman | 异常 | 已登录 | 不存在 id | 404 或业务失败;与项目约定一致 | | JP-BZ-API-011 | 修改 | 未同步成功 | 接口测试 | Postman | 需求 **4.3** | 已登录;目标 `kb=0` | `PUT /drugIncompatibility/standard` Body 含 `id`、主药/配伍/结果 | 成功;仍为 `kb=0`;详情与提交一致 | | JP-BZ-API-012 | 修改 | 已同步拒绝 | 接口测试 | Postman | 需求 **4.3**、矩阵 | 已登录;目标 `kb=1` | `PUT ...` 改任意业务字段 | 失败;数据不变 | | JP-BZ-API-013 | 删除 | 未同步成功 | 接口测试 | Postman | 需求 **4.4** | 已登录;`kb=0` | `DELETE /drugIncompatibility/standard/{id}` | 成功;记录消失(GET 无或失败) | | JP-BZ-API-014 | 删除 | 已同步拒绝 | 接口测试 | Postman | 需求 **4.4** | 已登录;`kb=1` | `DELETE ...` | 失败;提示先移出 | | JP-BZ-API-015 | 删除 | 批量 ids | 接口测试 | Postman | 技术方案 **3.5** | 已登录;多条 `kb=0` | `DELETE .../1,2,3` | 全部删除成功(与若依逗号分隔惯例一致) | | JP-BZ-API-016 | 删除 | 批量含已同步整单失败 | 接口测试 | Postman | 需求 **4.4** 批量 | ids 含未同步+已同步 | `DELETE .../id1,id2` | 失败;均未删或符合先校验实现;`msg` 可读 | | JP-BZ-API-017 | 同步知识库 | 未同步成功 | 接口测试 | Postman | 需求 **4.5** | 已登录;`kb=0` | `POST /drugIncompatibility/standard/syncKb/{id}` | `kb=1`;`kb_doc_id` 非空 | | JP-BZ-API-018 | 同步知识库 | 已同步重复调用 | 接口测试 | Postman | 矩阵、**4.5** 互斥 | 已登录;`kb=1` | `POST .../syncKb/{id}` | 失败;仍为已同步 | | JP-BZ-API-019 | 同步知识库 | 失败不翻转 | 接口测试 | Postman+Mock 对端 | 需求 **4.5** | **待 KB 对接**:对端失败 | `POST .../syncKb/{id}` | 仍为未同步;`msg` 可读可重试(占位阶段可跳过) | | JP-BZ-API-020 | 移出知识库 | 已同步成功 | 接口测试 | Postman | 需求 **4.6** | 已登录;`kb=1` | `POST /drugIncompatibility/standard/removeKb/{id}` | `kb=0`;`kb_doc_id` 空 | | JP-BZ-API-021 | 移出知识库 | 未同步调用 | 接口测试 | Postman | 矩阵 | 已登录;`kb=0` | `POST .../removeKb/{id}` | 失败 | | JP-BZ-API-022 | 移出知识库 | 失败保持已同步 | 接口测试 | Postman | 需求 **4.6** | **待 KB 对接**:对端失败 | `POST .../removeKb/{id}` | 仍为已同步(占位阶段可跳过) | | JP-BZ-API-023 | 关键路径 | 移出→改→再同步 | 接口测试 | Postman | 需求 **3.3** | 一条 `kb=1` | `removeKb`→`PUT`→`syncKb` | 最终 `kb=1`;业务与最后一次 PUT 一致 | | JP-BZ-API-024 | 鉴权 | 未登录 | 接口测试 | curl | 安全 | 无 Token/Cookie | `GET .../list` | 401 或重定向登录 | | JP-BZ-API-025 | 权限 | 无对应按钮权限 | 接口测试 | Postman | 需求 **第 7 章** | 仅 `list` 无 `add` | `POST /drugIncompatibility/standard` | 无权限失败 | | JP-BZ-API-026 | 错误提示 | 校验与业务失败可读 | 接口测试 | Postman | 需求 **第 6 章** | 已登录 | 触发校验失败、已同步删除等 | `msg` 区分输入不合法与状态不允许 | --- ## 三、界面测试用例(UI) **测试工具**:**Playwright** + **Chromium**(`channel: 'chrome'` 时使用本机 **Google Chrome**)。步骤与脚本映射:`page.goto`、`locator.fill`、`locator.click`、`expect`;删除/同步/移出等二次确认:`page.once('dialog')` 或页面内「确定」按钮。 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | JP-BZ-UI-001 | 列表 | 默认分页与排序 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.2** | 已登录;数据>默认页大小 | 进入药物禁配标准列表(路由占位) | 每页条数与项目一致;创建时间新在前 | | JP-BZ-UI-002 | 列表 | 主药关键字 | UI 测试 | Playwright+Chrome/Chromium | 主药模糊 | 存在主药含关键词记录 | 输入关键字→查询 | 表格含该行 | | JP-BZ-UI-003 | 列表 | 关键字不匹配「仅配伍含词」 | UI 测试 | Playwright+Chrome/Chromium | 与 **4.2** 默认维度 | 造数:主药不含「测」、配伍含「测」 | 关键字「测」→查询 | **不**出现该行 | | JP-BZ-UI-004 | 列表 | 同步状态与配伍条数/摘要 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.2** | 多条数据 | 查看列表列 | 可见未同步/已同步;可见配伍条数或等价摘要(若 UI 实现) | | JP-BZ-UI-005 | 列表 | 操作矩阵 | UI 测试 | Playwright+Chrome/Chromium | 需求 **第 5 章** | 未同步、已同步各一条 | 逐行查看按钮 | 未同步:查/改/删/同步,无移出;已同步:查/移出,无改/删/同步 | | JP-BZ-UI-006 | 新增 | 完整合法主流程 | UI 集成 | Playwright+Chrome/Chromium | 需求 **4.1**、**3.2** | 有新增权限 | 新增→主药+至少一条配伍+可选配伍结果→提交 | 成功提示;列表新行**未同步** | | JP-BZ-UI-007 | 新增 | 配伍行增减与边界 | UI 测试 | Playwright+Chrome/Chromium | 需求 **2.3**、**4.1** | 打开新增 | 用 `+`/`-` 增减行;试删至 0 条;两配伍同名;配伍=主药;配伍结果超长 | 对应校验失败;不能 0 条保存 | | JP-BZ-UI-008 | 详情 | 字段与同步状态 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.7** | 已有一条 | 点详情/查看 | 展示主药、有序配伍列表、配伍结果、同步状态 | | JP-BZ-UI-009 | 详情 | 已同步只读 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.7** | 已同步记录 | 打开详情 | 无保存式编辑或编辑入口不可用 | | JP-BZ-UI-010 | 详情 | 未同步可进编辑 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.7** | 未同步记录 | 详情或列表进编辑 | 可改并保存;列表/详情刷新后所见即所得 | | JP-BZ-UI-011 | 修改 | 未同步保存成功 | UI 集成 | Playwright+Chrome/Chromium | 需求 **4.3** | 未同步样本 | 改主药或配伍顺序/内容→保存 | 成功;仍为**未同步** | | JP-BZ-UI-012 | 修改 | 已同步不可改 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.3**、矩阵 | 已同步样本 | 尝试编辑 | 无编辑或保存被拒绝 | | JP-BZ-UI-013 | 知识库 | 同步成功 | UI 集成 | Playwright+Chrome/Chromium | 需求 **4.5** | 未同步记录 | 点「同步知识库」→确认(若有) | 状态变**已同步** | | JP-BZ-UI-014 | 知识库 | 已同步无「同步」入口 | UI 测试 | Playwright+Chrome/Chromium | 矩阵 | 已同步行 | 查看操作区 | 「同步」隐藏或禁用 | | JP-BZ-UI-015 | 知识库 | 同步失败提示与可重试 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.5**、**第 6 章** | 未同步;KB 失败环境或 Mock | 点同步 | 明确失败文案;未同步;可再试(占位阶段可跳过) | | JP-BZ-UI-016 | 知识库 | 移出成功 | UI 集成 | Playwright+Chrome/Chromium | 需求 **4.6** | 已同步记录 | 点「移出知识库」→确认 | 变**未同步**;可再编辑 | | JP-BZ-UI-017 | 知识库 | 未同步无「移出」 | UI 测试 | Playwright+Chrome/Chromium | 矩阵 | 未同步行 | 查看操作区 | 「移出」隐藏或禁用 | | JP-BZ-UI-018 | 知识库 | 移出失败提示 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.6** | 已同步;KB 移出失败(对接后) | 点移出 | 仍为已同步;可读错误(占位阶段可跳过) | | JP-BZ-UI-019 | 删除 | 未同步删除 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.4** | 未同步记录 | 删除→二次确认确定 | 记录从列表消失 | | JP-BZ-UI-020 | 删除 | 已同步不可删 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.4** | 已同步记录 | 尝试删除 | 无删除或失败并提示先移出 | | JP-BZ-UI-021 | 删除 | 取消确认不删 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.4** 交互 | 未同步 | 删除→取消 | 记录仍在 | | JP-BZ-UI-022 | 批量删除 | 含已同步整单失败 | UI 测试 | Playwright+Chrome/Chromium | 需求 **4.4** | 前端若支持多选删除 | 勾选未同步+已同步→删除 | 整单失败提示;数据未被部分误删 | | JP-BZ-UI-023 | 端到端 | 状态机全链路 | UI 集成 | Playwright+Chrome/Chromium | 需求 **3.2**、**3.3** | 可新建 | 新增(未同步)→同步(已同步)→详情只读→移出(未同步)→编辑保存→再同步(已同步)→移出→删除 | 每步与矩阵一致;最终删除成功 | | JP-BZ-UI-024 | 权限 | 只读/无写权限账号 | UI 测试 | Playwright+Chrome/Chromium | 需求 **第 7 章** | 无 `add`/`edit` 等 | 登录进入模块 | 无新增/编辑/删除或按钮不可见;若有 `list` 可查 | | JP-BZ-UI-025 | 回归 | 无发布/下架入口 | UI 测试 | Playwright+Chrome/Chromium | 需求 **第 1 章** 边界 | 任意状态 | 扫页面按钮与路由 | **无**「发布」「下架」类操作 | --- ## 四、用例与需求/设计追溯(摘要) | 需求章节 | 单元测试 | 接口测试 | UI 测试 | | --- | --- | --- | --- | | **4.1** 新增与字段规则 | UT-006~011、012 | API-005~008 | UI-006、UI-007 | | **4.2** 列表 | UT-024 | API-001~004 | UI-001~004 | | **4.3** 修改 | UT-002、013~015 | API-011、012 | UI-011、012 | | **4.4** 删除与幂等通知 | UT-003、020~022 | API-013~016 | UI-019~022 | | **4.5** 同步 | UT-004、016、017 | API-017~019 | UI-013~015 | | **4.6** 移出 | UT-005、018、019 | API-020~022 | UI-016~018 | | **4.7** 详情 | UT-023 | API-009、010 | UI-008~010 | | **第 5 章** 操作矩阵 | UT-002~005、017、019 | API-012、014、018、021 | UI-005、012、014、017、020 | | **第 6 章** 错误提示 | UT-006~010 | API-026 | UI-007、015 | | **3.3** 关键路径 | — | API-023 | UI-023 | | **2.3** 配伍约束 | UT-008~011 | API-007 | UI-007 | --- ## 五、Playwright 脚本提示(可选落地) ```typescript // 示例:使用本机 Chrome(需已安装);无则去掉 channel 使用内置 Chromium import { test, expect } from '@playwright/test'; test.use({ channel: 'chrome', headless: true }); test('JP-BZ-UI-023 摘要:新增→同步→移出→改→再同步→移出→删', async ({ page }) => { 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(); // 进入「药物禁配标准」菜单(文案与路由以实际为准) await page.getByText('药物禁配', { exact: false }).click(); // 新增:填写主药、配伍行(+ 添加行)、配伍结果;提交 // 列表:同步知识库 → 详情断言已同步 → 移出 → 编辑保存 → 再同步 → 移出 → 删除 // await expect(page.getByRole('row', { name: /未同步|已同步/ })).toBeVisible(); }); ``` **说明**:具体菜单路径、表单 `label`、配伍行「+/-」按钮、同步/移出确认框选择器以若依前端实现为准;建议将 `BASE_URL`、登录信息与 Page Object 抽离,便于 CI 与多环境复用。