# 牦牛资产档案管理 — 测试用例

> 依据：`牦牛资产档案管理功能需求.md`、`牦牛资产档案管理技术方案.md`  
> **接口 Base Path（示例）**：`/dataModel/yakAsset`；若含 `context-path` 或网关前缀须补齐。鉴权与若依一致（Cookie / Token）。

**通用前置（无特殊说明）**：具备本模块菜单与按钮权限的账号已登录；库中已有经同步或造数的档案样本（主表 `biz_yak_asset`，`del_flag=0`）。**资产状态**（`asset_status`）：`1` 正常、`2` 死淘、`3` 丢失、`4` 出栏。**生长数据种类**（`data_kind`）：`1` 实测、`2` 预测。详情含扩展基础字段及 `penRecords`、`batchRecords`。

**样本约定（示例）**：`yakNo=YAK20250001`；`assetStatus=2`；父编号 `YAK-F001`、母编号 `YAK-M001` 且库内存在可跳转；至少一头含生理时序、生长实测+预测、繁殖、饲喂子表数据。

**界面（UI）测试**：**Playwright** + **Chromium**（`channel: 'chrome'` 使用本机 **Google Chrome**）。菜单路径以 `livestockFinance/yakAsset/index` 为准。

---

## 一、单元测试用例

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-MYNZDA-UT-001 | 状态映射 | 第三方状态→本地 | 单元测试 | JUnit5 | §2.7 | 配置映射表 | 映射到 1～4；旧码如死亡→2、在养→1 | 未知码抛异常 |
| ZCZX-MYNZDA-UT-002 | 状态映射 | 非法本地状态 | 单元测试 | JUnit5 | 1～4 | 无 | `assetStatus` 为 0、5、null | 列表入参校验失败 |
| ZCZX-MYNZDA-UT-003 | 月龄计算 | 由出生日期计算 | 单元测试 | JUnit5 | §2.4 | `birthDate=2024-01-15` | `resolveAgeMonths(固定今日)` | 月龄与约定算法一致（月差或四舍五入规则固定） |
| ZCZX-MYNZDA-UT-004 | 列表校验 | 关键字 trim | 单元测试 | JUnit5 | 模糊查询 | 无 | `keyword` 含前后空格 | trim 后参与 `LIKE` |
| ZCZX-MYNZDA-UT-005 | 同步合并 | 按 yak_no 新增 | 单元测试 | JUnit5+Mockito | §5.3 | DB 无该编号 | `syncBundle(yakNo 新)` | `insert` 主表；子表批量插入 |
| ZCZX-MYNZDA-UT-006 | 同步合并 | 按 yak_no 更新 | 单元测试 | JUnit5+Mockito | §5.3 | DB 已有同编号 | `syncBundle` 字段变更 | `update` 主表；子表先删后插 |
| ZCZX-MYNZDA-UT-007 | 同步安全 | 失败不清库 | 单元测试 | JUnit5+Mockito | §5.3 | 已有档案 A | Mock 第三方抛超时；执行 sync | 档案 A 主表及子表条数不变 |
| ZCZX-MYNZDA-UT-008 | 同步安全 | 单头失败不回滚全局 | 单元测试 | JUnit5+Mockito | 事务边界 | 批次含 2 头，第 2 头校验失败 | `syncAll` | 第 1 头成功落库；`failCount≥1`；第 1 头数据保留 |
| ZCZX-MYNZDA-UT-009 | 牧场映射 | 映射成功写 pasture_id | 单元测试 | JUnit5+Mockito | §5.3 | `biz_pasture` 有匹配编码 | 同步带第三方牧场码 | `pasture_id` 非空；`pasture_name` 与主数据一致 |
| ZCZX-MYNZDA-UT-010 | 牧场映射 | 映射失败仅名称 | 单元测试 | JUnit5+Mockito | §5.3 | 无匹配主数据 | 同步带未知牧场码+名称 | `pasture_id` 空；`pasture_name` 为第三方名或「未关联」 |
| ZCZX-MYNZDA-UT-011 | 曲线查询 | 生理近 N 天 | 单元测试 | JUnit5+Mockito | §3.4.1 | Mock 45 天数据 | `selectPhysioChart(id, days=30)` | 仅返回最近 30 天内点；按 `collect_time` 升序或实现约定 |
| ZCZX-MYNZDA-UT-012 | 曲线查询 | 生长实测/预测分组 | 单元测试 | JUnit5+Mockito | §3.5.1 | 混合 data_kind | `selectGrowthChart(id, weight)` | `actual` 仅 kind=1；`forecast` 仅 kind=2 |
| ZCZX-MYNZDA-UT-013 | Service | 详情组装 | 单元测试 | JUnit5+Mockito | §3.2.1 | Mock 主表+六子表 | `selectDetailById` | 返回 `asset`+六数组；含 `penRecords`/`batchRecords` |
| ZCZX-MYNZDA-UT-014 | Service | 已删档案不可查 | 单元测试 | JUnit5+Mockito | del_flag | `del_flag=2` | `selectById` / `selectDetail` | null 或 `ServiceException` |
| ZCZX-MYNZDA-UT-015 | Service | byNo 查询 | 单元测试 | JUnit5+Mockito | §3.3 | 有效 yak_no | `selectDetailByYakNo` | 与按 id 详情结构一致 |
| ZCZX-MYNZDA-UT-016 | 并发 | 同步防重入 | 单元测试 | JUnit5 | §3.7 | 无 | 连续两次 `tryLock` 同步 | 第二次拒绝或排队；不重复写库 |
| ZCZX-MYNZDA-UT-017 | Mapper | 列表过滤排序 | 单元测试 | JUnit5 | §3.8 | 无 | 检查 `BizYakAssetMapper.xml` | `del_flag='0'`；`status_change_date desc, id desc`；`keyword` 模糊 `yak_no` |
| ZCZX-MYNZDA-UT-018 | Mapper | 子表按资产删除 | 单元测试 | JUnit5 | 同步删插 | 无 | 检查子表 Mapper `deleteByYakAssetId` | 同步前按 `yak_asset_id` 删除 |

---

## 二、接口测试用例

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-MYNZDA-API-001 | 列表 | 默认分页排序 | 接口测试 | Postman/curl | §5.1 | 已登录；多条档案 | `GET /dataModel/yakAsset/list` | `code=200`；`rows`≤20；`statusChangeDate` 新在前 |
| ZCZX-MYNZDA-API-002 | 列表 | 牦牛编号模糊 | 接口测试 | Postman | keyword | 已知 `YAK20250001` | `keyword=250001` | 命中含片段记录 |
| ZCZX-MYNZDA-API-003 | 列表 | 资产状态精确 | 接口测试 | Postman | §2.2 | 有不同状态样本 | `assetStatus=4` | 返回均为抵押中（status=4） |
| ZCZX-MYNZDA-API-004 | 列表 | 组合筛选 | 接口测试 | Postman | 多条件 | 已登录 | `keyword`+`assetStatus` | 同时满足 |
| ZCZX-MYNZDA-API-005 | 列表 | 非法资产状态 | 接口测试 | Postman | 1～4 | 已登录 | `assetStatus=99` | 失败；`msg` 可区分 |
| ZCZX-MYNZDA-API-006 | 列表 | 不含已删除 | 接口测试 | Postman | del_flag | 已知 id 已删 | `GET list` | 列表无该记录 |
| ZCZX-MYNZDA-API-007 | 列表 | 分页参数 | 接口测试 | Postman | 分页 | 数据>20 | `pageNum=2&pageSize=10` | 第 2 页；条数≤10 |
| ZCZX-MYNZDA-API-008 | 列表 | 无物联数据显示 | 接口测试 | Postman | §5.1 | 体温/步数为 null 的记录 | `GET list` | 字段为 null 或前端约定占位；接口不报错 |
| ZCZX-MYNZDA-API-009 | 详情 | 有效 id 全结构 | 接口测试 | Postman | §3.2.1、§5.5 | 含子表样本 | `GET /dataModel/yakAsset/{id}` | `data` 含 `asset`（扩展字段）、六类子表数组 |
| ZCZX-MYNZDA-API-010 | 详情 | 无效/已删 id | 接口测试 | Postman | 异常 | 已登录 | 不存在或 `del_flag=2` 的 id | `data` 空或业务失败 |
| ZCZX-MYNZDA-API-011 | 详情 | 按编号查询 | 接口测试 | Postman | §3.3 | 已知 yak_no | `GET .../byNo/YAK20250001` | 与按 id 详情字段一致 |
| ZCZX-MYNZDA-API-012 | 详情 | 编号不存在 | 接口测试 | Postman | 异常 | 已登录 | `GET .../byNo/NOT_EXIST` | 失败或 `data` 空 |
| ZCZX-MYNZDA-API-013 | 生理曲线 | 默认 30 天 | 接口测试 | Postman | §3.4 | 有>30 天时序 | `GET .../{id}/physioChart` | 点数覆盖近 30 天；含 bodyTemp/steps/envTemp |
| ZCZX-MYNZDA-API-014 | 生理曲线 | 自定义 days | 接口测试 | Postman | Query | 已登录 | `.../physioChart?days=7` | 仅近 7 天 |
| ZCZX-MYNZDA-API-015 | 生长曲线 | 实测与预测分组 | 接口测试 | Postman | §3.5.1 | 含 kind=1、2 | `GET .../{id}/growthChart?metric=weight` | `actual`、`forecast` 数组分离；无预测时 `forecast` 空 |
| ZCZX-MYNZDA-API-016 | 生长曲线 | 指标参数 | 接口测试 | Postman | metric | 有体高数据 | `metric=height` | 返回体高序列 |
| ZCZX-MYNZDA-API-017 | 同步 | 成功摘要 | 接口测试 | Postman/Mock | §5.3、§3.6.1 | Mock 第三方返回 1 新 1 更 | `POST .../sync` | `insertCount`/`updateCount`/`syncTime` 正确；`failCount=0` |
| ZCZX-MYNZDA-API-018 | 同步 | 第三方超时 | 接口测试 | Postman/Mock | §5.3 | Mock 超时 | `POST .../sync` | 失败；`msg` 提示第三方不可用；库内原档案不变 |
| ZCZX-MYNZDA-API-019 | 同步 | 鉴权失败 | 接口测试 | Postman/Mock | 第三方 | Mock 401 | `POST .../sync` | 失败；不误删数据 |
| ZCZX-MYNZDA-API-020 | 同步 | 更新后列表可见 | 接口测试 | Postman | 端到端 | 同步改 `realtimeTemp` | `POST sync`→`GET list` | 列表体温为新值 |
| ZCZX-MYNZDA-API-021 | 同步 | 子表覆盖 | 接口测试 | Postman/SQL | §5.3 | 同步前子表 N 条 | 同步后子表条数与第三方一致；旧 id 不残留 |
| ZCZX-MYNZDA-API-022 | 范围约束 | 无增删改接口 | 接口测试 | Postman | §3 本期无 | 已登录 | `POST/PUT/DELETE /dataModel/yakAsset`（非 sync） | 404/405 或无权限 |
| ZCZX-MYNZDA-API-023 | 鉴权 | 未登录 | 接口测试 | curl | 安全 | 无 Token | `GET .../yakAsset/list` | 401 或统一未登录 |
| ZCZX-MYNZDA-API-024 | 权限 | 无 list 权限 | 接口测试 | Postman | §6 | 无 list 角色 | `GET list` | 无权限失败 |
| ZCZX-MYNZDA-API-025 | 权限 | 无 sync 权限 | 接口测试 | Postman | §6 | 仅有 list+query | `POST .../sync` | 403 或业务无权限 |
| ZCZX-MYNZDA-API-026 | 权限 | 有 query 无 sync | 接口测试 | Postman | 分离 | query 账号 | `GET/{id}` 成功；`POST sync` 失败 | 符合权限矩阵 |
| ZCZX-MYNZDA-API-027 | 端到端 | 同步-查-详情 | 接口测试 | Postman | §4 | Mock 第三方 | `POST sync`→`GET list`→`GET/{id}`→`physioChart` | 各步成功；详情与子表一致 |
| ZCZX-MYNZDA-API-028 | 响应 | 失败可读 | 接口测试 | Postman | §7 | 已登录 | 触发非法状态、不存在 id、同步失败 | `code`、`msg` 可区分场景 |

---

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

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

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| ZCZX-MYNZDA-UI-001 | 列表 | 默认分页排序 | UI 测试 | Playwright+Chrome | §5.1 | 已登录；数据>20 | 进入「牦牛资产档案」菜单 | 默认每页 20；变更日期新在前 |
| ZCZX-MYNZDA-UI-002 | 列表 | 牦牛编号筛选 | UI 测试 | Playwright+Chrome | 模糊 | 有样本 | 输入编号片段→搜索 | 表格含匹配行 |
| ZCZX-MYNZDA-UI-003 | 列表 | 资产状态筛选 | UI 测试 | Playwright+Chrome | 精确 | 有多状态 | 选择「在养」→搜索 | 状态列均为在养 |
| ZCZX-MYNZDA-UI-004 | 列表 | 组合与重置 | UI 测试 | Playwright+Chrome | §5.2 | 已筛选 | 搜索→点「重置」 | 条件清空；恢复默认列表 |
| ZCZX-MYNZDA-UI-005 | 列表 | 展示列完整 | UI 测试 | Playwright+Chrome | §5.1 | 有数据 | 查看表头与首行 | 含编号、牧场、性别、月龄、体温、运动量、状态、变更日期、操作 |
| ZCZX-MYNZDA-UI-006 | 列表 | 无物联占位 | UI 测试 | Playwright+Chrome | §5.1 | 无体温样本 | 查看该行 | 显示「—」或「暂无」 |
| ZCZX-MYNZDA-UI-007 | 列表 | 无增删改按钮 | UI 测试 | Playwright+Chrome | §3 本期无 | 有写权限其他模块账号 | 进入列表页 | 无「新增」「编辑」「删除」；操作列仅「查看」 |
| ZCZX-MYNZDA-UI-008 | 同步 | 成功提示 | UI 测试 | Playwright+Chrome | §5.3 | 有 sync 权限；第三方可用 | 点「同步」→等待结束 | 成功提示含新增/更新摘要；列表数据刷新 |
| ZCZX-MYNZDA-UI-009 | 同步 | 执行中防重复 | UI 测试 | Playwright+Chrome | §5.2 | 有 sync 权限 | 同步进行中快速再次点击 | 按钮禁用或二次点击无效；仅一次请求 |
| ZCZX-MYNZDA-UI-010 | 同步 | 失败提示 | UI 测试 | Playwright+Chrome | §7 | Mock/断网第三方 | 点「同步」 | 明确失败提示；列表原数据仍在 |
| ZCZX-MYNZDA-UI-011 | 同步 | 无权限隐藏/禁用 | UI 测试 | Playwright+Chrome | §6 | 仅 list+query 账号 | 进入列表 | 无「同步」或点击被拒绝 |
| ZCZX-MYNZDA-UI-012 | 详情 | 入口与只读 | UI 测试 | Playwright+Chrome | §5.4 | 有 query 权限 | 列表点「查看」 | 进入详情；无保存/编辑按钮 |
| ZCZX-MYNZDA-UI-013 | 详情 | 顶部摘要条 | UI 测试 | Playwright+Chrome | §5.4 | 有完整档案 | 打开详情 | 展示编号、牧场、状态、性别、月龄 |
| ZCZX-MYNZDA-UI-014 | 详情 | 基础信息块 | UI 测试 | Playwright+Chrome | §5.5(1) | 有样本 | 滚动至基础信息 | 含批次、出生日期、入栏、来源、养殖方式等 |
| ZCZX-MYNZDA-UI-015 | 详情 | 系谱信息块 | UI 测试 | Playwright+Chrome | §5.5(2) | 有父母编号 | 查看系谱区 | 显示父/母编号；无则「—」 |
| ZCZX-MYNZDA-UI-016 | 详情 | 系谱跳转 | UI 测试 | Playwright+Chrome | §5.4 | 父编号库内存在 | 点击父亲编号链接 | 跳转该牛详情或新页打开 |
| ZCZX-MYNZDA-UI-017 | 详情 | 系谱不存在提示 | UI 测试 | Playwright+Chrome | §7 | 父编号不在库 | 点击父亲编号 | 提示不存在或不可跳转 |
| ZCZX-MYNZDA-UI-018 | 详情 | 个体生理当前值 | UI 测试 | Playwright+Chrome | §5.5(3) | 有物联数据 | 查看生理区 | 体温、运动量、环境温度、位置、采集时间正确 |
| ZCZX-MYNZDA-UI-019 | 详情 | 生理曲线图 | UI 测试 | Playwright+Chrome | §5.5(3) | 有近一月数据 | 查看曲线区域 | 近一月趋势；图例区分多指标 |
| ZCZX-MYNZDA-UI-020 | 详情 | 生理无数据 | UI 测试 | Playwright+Chrome | §7 | 无时序数据 | 打开详情 | 曲线区空态或「暂无数据」 |
| ZCZX-MYNZDA-UI-021 | 详情 | 生长列表默认 | UI 测试 | Playwright+Chrome | §5.5(4) | 有生长记录 | 进入生长区块 | 表格列齐全；最新记录在上 |
| ZCZX-MYNZDA-UI-022 | 详情 | 生长列表/曲线切换 | UI 测试 | Playwright+Chrome | §5.5(4) | 有实测+预测 | 点「切换」至曲线 | 展示曲线；实测与预测**不同颜色** |
| ZCZX-MYNZDA-UI-023 | 详情 | 生长仅实测 | UI 测试 | Playwright+Chrome | §5.5(4) | 仅实测数据 | 切换曲线模式 | 仅实测线；无预测图例 |
| ZCZX-MYNZDA-UI-024 | 详情 | 繁殖性能列表 | UI 测试 | Playwright+Chrome | §5.5(5) | 有繁殖数据 | 查看繁殖区块 | 含胎次、产犊间隔、成活率等列 |
| ZCZX-MYNZDA-UI-025 | 详情 | 饲喂数据列表 | UI 测试 | Playwright+Chrome | §5.5(6) | 有饲喂数据 | 查看饲喂区块 | 含开始/结束日龄、日补饲量、饲料类型 |
| ZCZX-MYNZDA-UI-026 | 详情 | 子块暂无数据 | UI 测试 | Playwright+Chrome | §7 | 某子表为空 | 打开对应区块 | 「暂无数据」；页面不报错 |
| ZCZX-MYNZDA-UI-027 | 时效 | 最近同步提示 | UI 测试 | Playwright+Chrome | §8 | 刚完成同步 | 查看列表或详情页 | 展示「数据截至」或 `lastSyncTime` 类文案 |
| ZCZX-MYNZDA-UI-028 | 端到端 | 同步-查-详情 | UI 集成 | Playwright+Chrome | §4 | sync+query 权限 | 同步→按编号搜索→查看→切换生长曲线 | 全流程无报错；数据一致 |
| ZCZX-MYNZDA-UI-029 | 权限 | 无菜单 | UI 测试 | Playwright+Chrome | §6 | 无本模块角色 | 登录后浏览菜单 | 无「牦牛资产档案」入口 |
| ZCZX-MYNZDA-UI-030 | 权限 | 无 query 不可看详情 | UI 测试 | Playwright+Chrome | §6 | 仅 list 无 query（若可配） | 尝试打开详情路由 | 403 或拦截 |

---

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

- 安装：`npm i -D @playwright/test`；`npx playwright install chromium`；本机 Chrome：`npx playwright install chrome`。  
- `playwright.config.ts`：`use: { channel: 'chrome', headless: false, locale: 'zh-CN', baseURL: 'http://localhost:80' }`；`storageState` 复用登录态。  
- 路由：`page.goto('/livestockFinance/yakAsset')`（以菜单 `component` 为准）。  
- 列表：`page.getByPlaceholder('牦牛编号')` 或标签相邻 input；状态下拉 `page.locator('.el-select').filter({ hasText: '资产状态' })`。  
- 同步：`page.getByRole('button', { name: '同步' })`；断言 `page.locator('.el-message--success')` 含「新增」「更新」。  
- 详情：`page.getByRole('button', { name: '查看' }).first().click()`；断言无 `保存`/`确定` 类编辑主按钮。  
- 生长切换：`page.getByRole('button', { name: /切换|曲线/ })`；曲线 canvas/svg 存在且图例含「实测」「预测」（文案以实现为准）。

---

## 覆盖对照

| 类别 | 单元 UT | 接口 API | 界面 UI |
| --- | --- | --- | --- |
| 正常流程 | UT-003、005～006、009～013、015 | API-001～004、009～011、013～017、020～021、027 | UI-001～006、008、012～025、028 |
| 异常流程 | UT-002、007～008、014 | API-005、010、012、018～019、023～026、028 | UI-010、017、020、026、029～030 |
| 业务约束 | UT-001～002、011～012、016～018 | API-003、005～006、015、021～022 | UI-003、007、009、022～023 |
| 同步与第三方 | UT-005～010、016 | API-017～021 | UI-008～011、027～028 |
| 详情六块/曲线 | UT-011～013 | API-009、013～016 | UI-012～026 |
| 权限 | — | API-023～026 | UI-011、029～030 |
| 只读无 CRUD | — | API-022 | UI-007、012 |

---

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

| 需求章节 | 要点 | 主要对应用例 |
| --- | --- | --- |
| §5.1 列表 | 编号模糊、状态精确、分页、列 | API-001～008；UI-001～006 |
| §5.2 工具栏 | 搜索、重置、同步防重 | UI-004、008～009；API-027 |
| §5.3 同步 | 合并键、子表、失败不清库、摘要 | UT-005～010、016；API-017～021；UI-008～011 |
| §5.4 详情 | 只读、摘要、系谱跳转 | API-009～012；UI-012～017 |
| §5.5 六块 | 生理曲线、生长切换/预测、繁殖、饲喂 | UT-011～013；API-013～016；UI-018～026 |
| §6～§7 | 权限、错误提示 | API-023～028；UI-010、011、017、029～030 |
| §3 范围外 | 无手工 CRUD | API-022；UI-007 |

---

## 修订记录

| 版本 | 说明 |
| --- | --- |
| 1.0 | 初版：单元 18、接口 28、UI 30；对齐功能/技术方案；Playwright+Chrome；编号前缀 **ZCZX-MYNZDA** |
