# 入场隔离登记 — 测试用例

> 依据：`入场隔离登记功能需求.md`、`入场隔离登记技术方案.md`  
> **接口 Base Path**：`/tradeMarket/entryIsolation`；鉴权与若依一致（Cookie / Token）。

**通用前置（无特殊说明）**：具备本模块权限的账号已登录（`tradeMarket:entryIsolation:list|query|add|edit|remove`）。关联主数据宜预置：

| 类型 | 样本 | 要点 |
| --- | --- | --- |
| 供应商 `biz_supplier` | **S1** `id=1` 扎西牧民合作社 | `del_flag=0` |
| 圈位 `biz_isolation_pen` | **P1** `01`、**P2** `02` | `del_flag=0` |
| 全局隔离天数 | **7** 天 | `biz_isolation_setting.default_days=7`（无则前端兜底 3） |

**合法新增 Body 示例**（2 头、分 2 圈）：

```json
{
  "entryTime": "2026-05-20 10:00:00",
  "supplierId": 1,
  "certNo": "QZ20260520001",
  "quantity": 2,
  "earTagList": ["E001", "E002"],
  "isolationDays": 7,
  "penAllocList": [
    { "penId": 1, "earTagList": ["E001"] },
    { "penId": 2, "earTagList": ["E002"] }
  ]
}
```

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

---

## 一、单元测试用例

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-RCGLDJ-UT-001 | 耳标解析 | 英文逗号拆分 | 单元测试 | JUnit5 | §2.5 | 无 | `EarTagCodec.parse("A,B,C")` | `["A","B","C"]` |
| ZCZX-RCGLDJ-UT-002 | 耳标解析 | 中文逗号 | 单元测试 | JUnit5 | §2.3 | 无 | `parse("A，B")` | 2 段 |
| ZCZX-RCGLDJ-UT-003 | 耳标解析 | trim 与空段 | 单元测试 | JUnit5 | §2.3 | 无 | `parse(" A , , B ")` | `["A","B"]` |
| ZCZX-RCGLDJ-UT-004 | 耳标解析 | 去重拒绝 | 单元测试 | JUnit5 | §2.3 | 无 | `parse("E1,E1")` | 抛异常或返回需校验失败 |
| ZCZX-RCGLDJ-UT-005 | 耳标解析 | 单段超长 | 单元测试 | JUnit5 | §2.5 | 无 | 33 字符耳标 | 校验失败 |
| ZCZX-RCGLDJ-UT-006 | 解除日期 | 自然日相加 | 单元测试 | JUnit5 | §2.5 | 无 | `calc("2026-05-20 10:00:00",7)` | `2026-05-27` |
| ZCZX-RCGLDJ-UT-007 | 解除日期 | 跨月 | 单元测试 | JUnit5 | §2.5 | 无 | `entry=2026-05-28`，`days=5` | `2026-06-02` |
| ZCZX-RCGLDJ-UT-008 | 一致性 | R1 数量=耳标数 | 单元测试 | JUnit5 | §2.6 | 无 | `quantity=3`，耳标 2 个 | 失败 |
| ZCZX-RCGLDJ-UT-009 | 一致性 | R2 分圈数量之和 | 单元测试 | JUnit5 | §2.6 | 总量 2 | 分圈 1+2 | 失败 |
| ZCZX-RCGLDJ-UT-010 | 一致性 | R3 耳标遗漏 | 单元测试 | JUnit5 | §2.6 | 主表 E1,E2 | 分圈仅 E1 | 失败 |
| ZCZX-RCGLDJ-UT-011 | 一致性 | R4 跨圈重复耳标 | 单元测试 | JUnit5 | §2.6 | 主表 E1,E2 | 两圈均含 E1 | 失败 |
| ZCZX-RCGLDJ-UT-012 | 一致性 | R5 本圈数量 | 单元测试 | JUnit5 | §2.6 | 无 | 圈行 quantity=2，耳标 1 个 | 失败 |
| ZCZX-RCGLDJ-UT-013 | 一致性 | 合法全量 | 单元测试 | JUnit5 | §2.6 | 合法 Body | `validate(saveDto)` | 通过 |
| ZCZX-RCGLDJ-UT-014 | 一致性 | 分圈为空 | 单元测试 | JUnit5 | §5.1 | 无 | `penAllocList=[]` | 失败 |
| ZCZX-RCGLDJ-UT-015 | 一致性 | 同登记重复圈位 | 单元测试 | JUnit5 | §5.1.3 | 无 | 两条 `penId=1` | 失败 |
| ZCZX-RCGLDJ-UT-016 | 外键 | 供应商已删 | 单元测试 | JUnit5+Mockito | §2.8 | `del_flag=2` | `validate` | 失败 |
| ZCZX-RCGLDJ-UT-017 | 外键 | 圈位已删 | 单元测试 | JUnit5+Mockito | §2.8 | 圈位已删 | `validate` | 失败 |
| ZCZX-RCGLDJ-UT-018 | 字段校验 | 检疫证号长度 | 单元测试 | JUnit5 | §5.1 | 无 | 空、51 字、50 字 | 空/51 失败；50 通过 |
| ZCZX-RCGLDJ-UT-019 | 字段校验 | 隔离天数范围 | 单元测试 | JUnit5 | §5.1 | 无 | `0`、`1`、`3650`、`3651` | 0/3651 失败；1/3650 通过 |
| ZCZX-RCGLDJ-UT-020 | 文件校验 | 检疫证后缀 | 单元测试 | JUnit5 | §2.7 | 无 | `.exe`、`.pdf`、`.PDF` | exe 失败；pdf 通过 |
| ZCZX-RCGLDJ-UT-021 | Service | 新增主从落库 | 单元测试 | JUnit5+Mockito | §3.3 | Mock Mapper | `insert` 合法样本 | 主表 `del_flag=0`；子表 2 行；`expected_release_date` 已算 |
| ZCZX-RCGLDJ-UT-022 | Service | 修改覆盖分圈 | 单元测试 | JUnit5+Mockito | §3.3 | 已有 2 条子表 | `update` 新 `penAllocList` | 旧子表删净；新子表插入 |
| ZCZX-RCGLDJ-UT-023 | Service | 逻辑删除 | 单元测试 | JUnit5+Mockito | §3.4 | Mock | `remove(id)` | 主表 `del_flag=2` |
| ZCZX-RCGLDJ-UT-024 | Service | 删除有关联 | 单元测试 | JUnit5+Mockito | §2.9 | `hasReference=true` | `remove` | 抛 `ServiceException` |

---

## 二、接口测试用例

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-RCGLDJ-API-001 | 列表 | 默认分页排序 | 接口测试 | Postman | §3.1 | 有登记数据 | `GET /list` | `code=200`；≤20 条；`entryTime` 倒序 |
| ZCZX-RCGLDJ-API-002 | 列表 | 进场日期区间 | 接口测试 | Postman | §5.2.1 | 已知进场日 | `entryDateStart/End` 含该日 | 命中；区间外不出现 |
| ZCZX-RCGLDJ-API-003 | 列表 | 检疫证号模糊 | 接口测试 | Postman | §5.2.1 | 证号 `QZ2026` | `certNo=QZ2026` | 含片段行 |
| ZCZX-RCGLDJ-API-004 | 列表 | 供应商精确 | 接口测试 | Postman | §5.2.1 | S1、S2 各有登记 | `supplierId=S1` | 仅 S1 记录 |
| ZCZX-RCGLDJ-API-005 | 列表 | 组合筛选 | 接口测试 | Postman | 多条件 | 已登录 | 日期+证号+供应商 | 同时满足才命中 |
| ZCZX-RCGLDJ-API-006 | 列表 | 不含已删除 | 接口测试 | Postman | 逻辑删除 | 某 id 已删 | `GET /list` | 无该 id |
| ZCZX-RCGLDJ-API-007 | 新增 | 合法全量 | 接口测试 | Postman | §5.1 | S1、P1/P2 | `POST` 合法 Body | `code=200`；`expectedReleaseDate=2026-05-27` |
| ZCZX-RCGLDJ-API-008 | 新增 | 含检疫证文件 | 接口测试 | Postman | §2.7 | 已 `/common/upload` pdf | Body 带 `certFileUrl/Path` | 成功；详情可下载 |
| ZCZX-RCGLDJ-API-009 | 新增 | 缺供应商 | 接口测试 | Postman | 异常 | 已登录 | 无 `supplierId` | 失败 |
| ZCZX-RCGLDJ-API-010 | 新增 | 缺检疫证号 | 接口测试 | Postman | 异常 | 已登录 | 空 `certNo` | 失败 |
| ZCZX-RCGLDJ-API-011 | 新增 | R1 数量≠耳标数 | 接口测试 | Postman | §2.6 R1 | 已登录 | `quantity=2`，耳标 1 个 | 失败；msg 含数量/耳标 |
| ZCZX-RCGLDJ-API-012 | 新增 | R2 分圈数量之和 | 接口测试 | Postman | §2.6 R2 | 总量 2 | 分圈 2+1 | 失败 |
| ZCZX-RCGLDJ-API-013 | 新增 | R3 未分圈耳标 | 接口测试 | Postman | §2.6 R3 | 主表 E1,E2 | 分圈仅 E1 | 失败 |
| ZCZX-RCGLDJ-API-014 | 新增 | R4 耳标跨圈重复 | 接口测试 | Postman | §2.6 R4 | 主表 E1,E2 | 两圈均 E1 | 失败 |
| ZCZX-RCGLDJ-API-015 | 新增 | 重复圈位 | 接口测试 | Postman | §5.1.3 | 已登录 | 两条相同 `penId` | 失败 |
| ZCZX-RCGLDJ-API-016 | 新增 | 无效供应商 | 接口测试 | Postman | §2.8 | 已删供应商 id | `POST` | 失败 |
| ZCZX-RCGLDJ-API-017 | 新增 | 无效圈位 | 接口测试 | Postman | §2.8 | 已删 `penId` | `POST` | 失败 |
| ZCZX-RCGLDJ-API-018 | 新增 | 检疫证后缀非法 | 接口测试 | Postman | §2.7 | 已登录 | `certFilePath` 为 `.exe` | 失败 |
| ZCZX-RCGLDJ-API-019 | 新增 | 隔离天数非法 | 接口测试 | Postman | §5.1 | 已登录 | `isolationDays=0`/`3651` | 失败 |
| ZCZX-RCGLDJ-API-020 | 新增 | 主表耳标重复 | 接口测试 | Postman | §2.3 | 已登录 | `earTagList=["E1","E1"]` | 失败 |
| ZCZX-RCGLDJ-API-021 | 新增 | 分圈耳标超集 | 接口测试 | Postman | §5.1.3 | 主表 E1 | 分圈含 E9 | 失败 |
| ZCZX-RCGLDJ-API-022 | 详情 | 有效 id | 接口测试 | Postman | §5.4 | 有登记 E1 | `GET /{id}` | 含 `supplierName`、`earTagList`、`penAllocList` |
| ZCZX-RCGLDJ-API-023 | 详情 | 无效/已删 id | 接口测试 | Postman | 异常 | 已登录 | 不存在或已删 | 失败或 `data` 空 |
| ZCZX-RCGLDJ-API-024 | 修改 | 改证号与分圈 | 接口测试 | Postman | §5.3 | 有 E1 | `PUT` 改 `certNo`、重排分圈 | 成功；子表全量覆盖 |
| ZCZX-RCGLDJ-API-025 | 修改 | 进场时间联动日期 | 接口测试 | Postman | §2.5 | 有 E1 | `PUT` `entryTime`+`isolationDays` | `expectedReleaseDate` 重算 |
| ZCZX-RCGLDJ-API-026 | 修改 | 违反 R1 | 接口测试 | Postman | §2.6 | 有 E1 | `PUT` 数量与耳标不一致 | 失败 |
| ZCZX-RCGLDJ-API-027 | 修改 | 不存在 id | 接口测试 | Postman | 异常 | 已登录 | 伪造 id `PUT` | 失败 |
| ZCZX-RCGLDJ-API-028 | 删除 | 单条逻辑删 | 接口测试 | Postman | §5.5 | 无关联新行 | `DELETE /{id}` | 成功；列表不可见 |
| ZCZX-RCGLDJ-API-029 | 删除 | 有关联拒绝 | 接口测试 | Postman | §2.9 | `hasReference=true` | `DELETE` | 失败；提示关联 |
| ZCZX-RCGLDJ-API-030 | 删除 | 重复删除 | 接口测试 | Postman | 幂等 | 已删 id | 再次 `DELETE` | 失败或不存在 |
| ZCZX-RCGLDJ-API-031 | 端到端 | CRUD 串联 | 接口测试 | Postman | §4 | 已登录 | `POST`→`list`→`GET`→`PUT`→`DELETE` | 每步 `code=200` |
| ZCZX-RCGLDJ-API-032 | 鉴权 | 未登录 | 接口测试 | curl | 安全 | 无 Token | `GET /list` | 401 或统一未登录 |
| ZCZX-RCGLDJ-API-033 | 权限 | 无新增权限 | 接口测试 | Postman | §6 | 仅 list | `POST` | 无权限失败 |
| ZCZX-RCGLDJ-API-034 | 权限 | 无删除权限 | 接口测试 | Postman | §6 | 无 remove | `DELETE` | 无权限失败 |
| ZCZX-RCGLDJ-API-035 | 响应 | 失败可读 | 接口测试 | Postman | §8 | 已登录 | 触发 R1、重复圈位 | `msg` 可区分场景 |

---

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

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

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-RCGLDJ-UI-001 | 列表 | 默认展示 | UI 测试 | Playwright+Chrome | §5.2.3 | 已登录；有数据 | 进入「入场隔离登记」 | 含进场时间、供应商、检疫证号、数量、圈位分配、隔离天数、解除日期、操作 |
| ZCZX-RCGLDJ-UI-002 | 列表 | 进场日期筛选 | UI 测试 | Playwright+Chrome | §5.2.1 | 已知日期登记 | 选日期范围→搜索 | 仅范围内记录 |
| ZCZX-RCGLDJ-UI-003 | 列表 | 检疫证号模糊 | UI 测试 | Playwright+Chrome | §5.2.1 | 有证号含 QZ | 填片段→搜索 | 命中对应行 |
| ZCZX-RCGLDJ-UI-004 | 列表 | 供应商筛选 | UI 测试 | Playwright+Chrome | §5.2.1 | 多供应商数据 | 下拉选 S1→搜索 | 仅 S1 |
| ZCZX-RCGLDJ-UI-005 | 列表 | 重置 | UI 测试 | Playwright+Chrome | §5.2 | 已筛选 | 搜索→重置 | 条件清空；列表恢复 |
| ZCZX-RCGLDJ-UI-006 | 列表 | 圈位分配表 | UI 测试 | Playwright+Chrome | §5.2.3 | 有分圈数据 | 点击「圈位分配表」 | 弹窗展示圈位编号、数量、耳标 |
| ZCZX-RCGLDJ-UI-007 | 新增 | 进场时间默认 | UI 测试 | Playwright+Chrome | §5.1 | 有 add 权限 | 打开新增弹窗 | 进场时间≈当前时刻 |
| ZCZX-RCGLDJ-UI-008 | 新增 | 供应商模糊选 | UI 测试 | Playwright+Chrome | §2.8 | 有 S1 | 供应商输入关键字→选 S1 | 选中后展示名称 |
| ZCZX-RCGLDJ-UI-009 | 新增 | 隔离天数默认 | UI 测试 | Playwright+Chrome | §2.5 | 全局 7 天 | 打开新增 | 隔离天数默认 7 |
| ZCZX-RCGLDJ-UI-010 | 新增 | 预计解除日期联动 | UI 测试 | Playwright+Chrome | §2.5 | 新增弹窗 | 改进场日期或隔离天数 | 解除日期自动更新 |
| ZCZX-RCGLDJ-UI-011 | 新增 | 上传检疫证合法 | UI 测试 | Playwright+Chrome | §2.7 | 有 pdf≤30MB | 上传 pdf | 成功；可预览/删除 |
| ZCZX-RCGLDJ-UI-012 | 新增 | 上传格式/大小非法 | UI 测试 | Playwright+Chrome | §2.7 | 有 exe 或超大文件 | 选择上传 | 提示格式或 10/30MB 限制 |
| ZCZX-RCGLDJ-UI-013 | 新增 | 添加分圈成功 | UI 测试 | Playwright+Chrome | §5.1.3 | 主表耳标 E1,E2 | 添加分圈→P1 选 E1→P2 选 E2→确定 | 表格 2 行；数量各 1 |
| ZCZX-RCGLDJ-UI-014 | 新增 | 分圈耳标不可重复选 | UI 测试 | Playwright+Chrome | §5.1.3 R4 | 已分圈 E1 | 再添加分圈 | 下拉无 E1 或选后校验失败 |
| ZCZX-RCGLDJ-UI-015 | 新增 | 同圈位不可重复 | UI 测试 | Playwright+Chrome | §5.1.3 | 已占 P1 | 再添加 P1 | 提示圈位已添加 |
| ZCZX-RCGLDJ-UI-016 | 新增 | 保存合法全流程 | UI 测试 | Playwright+Chrome | §4.2 | 权限齐备 | 填主表+分圈→确定 | 成功提示；列表新行数据正确 |
| ZCZX-RCGLDJ-UI-017 | 新增 | R1 前端校验 | UI 测试 | Playwright+Chrome | §2.6 | 新增 | 数量 2、耳标 1 个→保存 | 校验失败；不提交 |
| ZCZX-RCGLDJ-UI-018 | 新增 | 未分圈保存 | UI 测试 | Playwright+Chrome | §5.1 | 新增 | 填主表无分圈→保存 | 提示须添加分圈 |
| ZCZX-RCGLDJ-UI-019 | 新增 | 取消 | UI 测试 | Playwright+Chrome | §5.1.4 | 新增 | 填数据→取消 | 弹窗关；无新行 |
| ZCZX-RCGLDJ-UI-020 | 查看 | 只读含分圈 | UI 测试 | Playwright+Chrome | §5.4 | 有登记 | 点击查看 | 主表只读；分圈表只读；有检疫证链接 |
| ZCZX-RCGLDJ-UI-021 | 编辑 | 改分圈保存 | UI 测试 | Playwright+Chrome | §5.3 | 有登记 | 编辑→删一行分圈→重分圈→确定 | 列表/详情已更新 |
| ZCZX-RCGLDJ-UI-022 | 编辑 | 分圈行删除 | UI 测试 | Playwright+Chrome | §5.1.2 | 编辑 | 分圈表点删除 | 行移除 |
| ZCZX-RCGLDJ-UI-023 | 删除 | 确认删除 | UI 测试 | Playwright+Chrome | §5.5 | 无关联行 | 删除→确认 | 行消失 |
| ZCZX-RCGLDJ-UI-024 | 删除 | 取消删除 | UI 测试 | Playwright+Chrome | §5.5 | 任意行 | 删除→取消 | 行仍在 |
| ZCZX-RCGLDJ-UI-025 | 端到端 | 全流程 | UI 集成 | Playwright+Chrome | §4 | 权限齐备 | 新增→筛选→圈位表→查看→编辑→删除 | 无报错；数据一致 |
| ZCZX-RCGLDJ-UI-026 | 权限 | 只读角色 | UI 测试 | Playwright+Chrome | §6 | 仅 list/query | 进入模块 | 无新增/编辑/删除按钮 |
| ZCZX-RCGLDJ-UI-027 | 查看 | 从详情进编辑 | UI 测试 | Playwright+Chrome | §5.4 | 查看弹窗 | 点「编辑」 | 进入编辑弹窗；数据回显 |

---

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

- 安装：`npm i -D @playwright/test`；`npx playwright install chrome`。  
- 配置：`use: { channel: 'chrome', locale: 'zh-CN', baseURL: 'http://localhost:80' }`；`storageState` 复用登录态。  
- 路由：`page.goto('/tradeMarket/entryIsolation')`（以菜单 `component` 为准）。  
- 新增：`page.getByRole('button', { name: '新增' }).click()` → 填进场时间、选供应商、检疫证号、数量、耳标 → `getByRole('button', { name: '添加分圈' })` 完成分圈 → 确定。  
- 分圈子窗：`page.getByLabel('圈位编号').click()` 选圈位 → 耳标多选 → 确定。  
- 列表筛选：`page.getByLabel('进场日期')` 用 `daterange`；`getByRole('button', { name: '搜索' }).click()`。

---

## 覆盖对照

| 类别 | 单元 UT | 接口 API | 界面 UI |
| --- | --- | --- | --- |
| 正常流程 | UT-013、021～022 | API-007～008、022、024～025、031 | UI-006～011、013、016、020～021、025 |
| 异常流程 | UT-004、008～012、014～017、024 | API-009～010、011～021、023、026～030 | UI-012、017～018、023～024 |
| 业务约束 R1～R5 | UT-008～015 | API-011～015、020～021、026 | UI-013～018 |
| 解除日期计算 | UT-006～007 | API-007、025 | UI-009～010 |
| 耳标解析 | UT-001～005 | API-020 | UI-013～014 |
| 关联主数据 | UT-016～017 | API-016～017 | UI-008 |
| 检疫证文件 | UT-020 | API-008、018 | UI-011～012 |
| 列表筛选 | — | API-002～005 | UI-002～005 |
| 逻辑删除 | UT-023 | API-006、028～030 | UI-023 |
| 权限/鉴权 | — | API-032～034 | UI-026 |

---

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

| 需求章节 | 要点 | 主要对应用例 |
| --- | --- | --- |
| §5.1 新增 | 主表+分圈、校验 | UT-008～015、021；API-007～021；UI-007～019 |
| §5.2 列表 | 日期/证号/供应商 | API-002～005；UI-002～006 |
| §5.3 修改 | 全量可改、重算日期 | UT-022；API-024～026；UI-021～022 |
| §5.4 查看 | 只读、圈位分配表 | API-022；UI-006、020、027 |
| §5.5 删除 | 逻辑删、关联 | UT-023～024；API-028～030；UI-023～024 |
| §2.6 一致性 | R1～R5 | UT-008～015；API-011～015；UI-013～018 |
| §2.5 解除日期 | 自动计算 | UT-006～007；API-007、025；UI-010 |
| §2.7 检疫证 | 后缀/大小 | UT-020；API-008、018；UI-011～012 |
| §2.8 关联 | 供应商/圈位 | UT-016～017；API-016～017；UI-008 |
| §6 权限 | 按钮级 | API-032～034；UI-026 |

---

## 修订记录

| 版本 | 说明 |
| --- | --- |
| 1.0 | 初版：单元 24、接口 35、UI 27；覆盖 R1～R5、主从表 CRUD、筛选、检疫证、Playwright+Chrome；前缀 **ZCZX-RCGLDJ** |
