# 牦牛存栏数据填报 — 测试用例 > 依据:`牦牛存栏数据填报功能需求.md`、`牦牛存栏数据填报技术方案.md` > **接口 Base Path(示例)**:`/dataModel/yakHerdInventory` > **模板文件**:`2026年.xlsx` 第一个 Sheet > **乡镇样本**:巴青乡、江绵乡、岗切乡、雅安镇、拉西镇、本塔乡、杂色镇、贡日乡、玛如乡、阿秀乡(`sys_dept`,`parent_id=100`,`order_num>12`) **通用前置**:已登录且具备模块权限;`sys_dept` 已执行 `sql/sys_dept_import_town.sql`;测试库无冲突数据或已隔离。 --- ## 一、单元测试用例 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | ZCZX-MYCLTB-UT-001 | 年份 | 可选年份范围 | 单元测试 | JUnit5 | §2.2 | 固定时钟 2026 | `YearOptionsResolver.resolve()` | 返回 2026~2021 共 6 年 | | ZCZX-MYCLTB-UT-002 | 乡镇 | 字典过滤 | 单元测试 | JUnit5 | §2.3 | Mock dept 表 | `TownDeptSupport.listReportTowns()` | 仅 `parent_id=100` 且 `order_num>12` | | ZCZX-MYCLTB-UT-003 | 校验 | 必填年份乡镇 | 单元测试 | JUnit5 | §5.2 | 无 | `validate(row)` 缺 `statYear` | 抛 `ServiceException` | | ZCZX-MYCLTB-UT-004 | 校验 | 负数拒绝 | 单元测试 | JUnit5 | §2.5 | 无 | `yakTotal=-1` | 校验失败 | | ZCZX-MYCLTB-UT-005 | 唯一性 | 同年同月同乡镇 | 单元测试 | JUnit5+Mockito | §5.2 | 已存在 2026-05+巴青乡 | `insert` 同键 | 失败「已填报」 | | ZCZX-MYCLTB-UT-006 | 新增 | 新增成功 | 单元测试 | JUnit5+Mockito | §5.2 | 无同年同乡镇记录 | `insert` | 成功 | | ZCZX-MYCLTB-UT-007 | 导入解析 | 识别表头行 | 单元测试 | JUnit5 | §3.8.1 | `2026年.xlsx` | `detectHeaderRow(sheet)` | 定位含「乡镇」表头 | | ZCZX-MYCLTB-UT-008 | 导入解析 | 乡镇名匹配 | 单元测试 | JUnit5 | §5.6 | 行「杂色镇」 | `resolveTownDeptId` | 返回对应 `dept_id` | | ZCZX-MYCLTB-UT-009 | 导入解析 | 未知乡镇 | 单元测试 | JUnit5 | §5.6 | 行「不存在乡」 | 解析 | 记入 `failMessages` | | ZCZX-MYCLTB-UT-010 | 导入解析 | 空行终止 | 单元测试 | JUnit5 | §5.6 | 数据后空行 | `parseRows` | 仅 10 乡镇行 | | ZCZX-MYCLTB-UT-011 | 导入 | upsert 新增 | 单元测试 | JUnit5+Mockito | §5.6 | DB 无 2025+本塔乡 | `importYear(2025,file)` | `insertCount>=1` | | ZCZX-MYCLTB-UT-012 | 导入 | upsert 更新 | 单元测试 | JUnit5+Mockito | §5.6 | 已有 2026+各乡镇 | 同一 xlsx 再导入 | `updateCount=10`;`insertCount=0` | | ZCZX-MYCLTB-UT-013 | 修改 | 记录不存在 | 单元测试 | JUnit5+Mockito | §5.3 | id 不存在 | `update` | 抛 `ServiceException` | | ZCZX-MYCLTB-UT-014 | 删除 | 物理删除 | 单元测试 | JUnit5+Mockito | §5.4 | 有效 id | `deleteBizYakHerdInventoryByIds` | 调用 Mapper 物理删除 | | ZCZX-MYCLTB-UT-015 | 数据权限 | 乡镇账号过滤 | 单元测试 | JUnit5+Mockito | §6 | 用户 dept=杂色镇 | `selectList` | 仅本乡镇 | | ZCZX-MYCLTB-UT-016 | 预留字段 | village_dept_id 可空 | 单元测试 | JUnit5 | §2.4 | 无 | `insert` 不传 `villageDeptId` | 成功 | | ZCZX-MYCLTB-UT-017 | 预留字段 | village_dept_id 父子校验 | 单元测试 | JUnit5+Mockito | §2.4 | 乡镇 A、村居 B 非子节点 | `insert` 带错误 `villageDeptId` | 失败(若启用校验)或成功仅存 id | | ZCZX-MYCLTB-UT-018 | 导出 | 按年填充模板 | 单元测试 | JUnit5 | §5.7 | 模板+1 乡镇样本 | `YakHerdInventoryExcelExporter.export` | 返回 xlsx;解析含对应存栏数 | | ZCZX-MYCLTB-UT-019 | 导出 | 全县乡镇行数 | 单元测试 | JUnit5 | §5.7 | 10 乡镇字典 | `export(2026, towns, map)` | 解析数据行 + 合计行 | | ZCZX-MYCLTB-UT-020 | 月份 | 未来月拒绝 | 单元测试 | JUnit5 | §2.2.1 | 当前年 | `validateStatPeriod(2026, 未来月)` | 抛 `ServiceException` | | ZCZX-MYCLTB-UT-021 | 月份 | 月份选项 | 单元测试 | JUnit5 | §2.2.1 | 无 | `resolveMonthOptions()` | 返回 1~12 | ## 二、接口测试用例 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | ZCZX-MYCLTB-API-001 | 列表 | 默认分页 | 接口测试 | Postman | §5.1 | 已登录;有样本 | `GET /list` | `code=200`;含所属年份、乡镇、村居数、牧户数、存栏数、公牛/母牛存栏数 | | ZCZX-MYCLTB-API-002 | 列表 | 按年份筛选 | 接口测试 | Postman | §5.1 | 有 2025、2026 数据 | `statYear=2026` | 仅 2026 | | ZCZX-MYCLTB-API-002a | 列表 | 按年月筛选 | 接口测试 | Postman | §5.1 | 同 year 多 month | `statYear=2026&statMonth=12` | 仅 2026 年 12 月 | | ZCZX-MYCLTB-API-003 | 列表 | 按乡镇筛选 | 接口测试 | Postman | §5.1 | 已知 dept_id | `townDeptId=` | 仅该乡镇 | | ZCZX-MYCLTB-API-004 | 列表 | 组合筛选 | 接口测试 | Postman | §5.1 | 已登录 | 年+月+乡镇 | 交集结果 | | ZCZX-MYCLTB-API-005 | 详情 | 全字段 | 接口测试 | Postman | §5.5 | 有效 id | `GET /{id}` | 返回全部字段(含 `villageDeptId`、分龄、种公牛等);列表 VO 不含的字段均在详情中 | | ZCZX-MYCLTB-API-006 | 新增 | 必填成功 | 接口测试 | Postman | §5.2 | 无重复 | `POST` 最小必填 | 成功 | | ZCZX-MYCLTB-API-007 | 新增 | 缺年份 | 接口测试 | Postman | §5.2 | 已登录 | 缺 `statYear` | 失败 | | ZCZX-MYCLTB-API-008 | 新增 | 缺乡镇 | 接口测试 | Postman | §5.2 | 已登录 | 缺 `townDeptId` | 失败 | | ZCZX-MYCLTB-API-009 | 新增 | 重复同年月乡镇 | 接口测试 | Postman | §5.2 | 已有记录 | 再 `POST` 同键 | 失败 | | ZCZX-MYCLTB-API-010 | 修改 | 更新指标 | 接口测试 | Postman | §5.3 | 有效 id | `PUT` 改 `yakTotal` | 成功;详情为新值 | | ZCZX-MYCLTB-API-011 | 删除 | 物理删除 | 接口测试 | Postman | §5.4 | 有效 id | `DELETE /{id}` | 成功;记录从库中移除 | | ZCZX-MYCLTB-API-012 | 下拉 | 年份选项 | 接口测试 | Postman | §2.2 | 已登录 | `GET /yearOptions` | 6 个年份 | | ZCZX-MYCLTB-API-013 | 下拉 | 乡镇选项 | 接口测试 | Postman | §2.3 | 已登录 | `GET /townOptions` | 10 个乡镇;`order_num>12` | | ZCZX-MYCLTB-API-014 | 导入 | 全量乡镇 | 接口测试 | Postman | §5.6 | 空库 2026-05 | `POST /importData`+`2026年.xlsx`+`statYear=2026&statMonth=5` | `insertCount=10`;`failCount=0` | | ZCZX-MYCLTB-API-015 | 导入 | 覆盖更新 | 接口测试 | Postman | §5.6 | 已有 2026 全量 | 改 Excel 一行再导入 | `updateCount>=1` | | ZCZX-MYCLTB-API-016 | 导入 | 缺填报年份 | 接口测试 | Postman | §5.6 | 已登录 | 仅上传文件 | 失败 | | ZCZX-MYCLTB-API-017 | 导入 | 非 xlsx | 接口测试 | Postman | §5.6 | 已登录 | 上传 `.csv` | 失败 | | ZCZX-MYCLTB-API-018 | 权限 | 无 add | 接口测试 | Postman | §6 | 仅 list 角色 | `POST /` | 403 | | ZCZX-MYCLTB-API-019 | 权限 | 无 import | 接口测试 | Postman | §6 | 无 import | `POST /importData` | 403 | | ZCZX-MYCLTB-API-020 | 端到端 | 导入-查-详情 | 接口测试 | Postman | §4 | 空库 | 导入 2026→list→detail | 数据一致 | | ZCZX-MYCLTB-API-021 | 导出 | 按年月导出 | 接口测试 | Postman/MockMvc | §5.7 | 有 2026-05 数据 | `GET /export?statYear=2026&statMonth=5` | `200`;xlsx | | ZCZX-MYCLTB-API-022 | 导出 | 缺 statMonth | 接口测试 | Postman | §5.7 | 已登录 | `GET /export?statYear=2026` | 失败 | | ZCZX-MYCLTB-API-023 | 导出 | 非法年份 | 接口测试 | Postman | §5.7 | 已登录 | `statYear=1999` | 失败 | | ZCZX-MYCLTB-API-024 | 权限 | 无 export | 接口测试 | Postman | §6 | 无 export | `GET /export?statYear=2026&statMonth=5` | 403 | | ZCZX-MYCLTB-API-025 | 端到端 | 导出-再导入 | 接口测试 | Postman | §5.7 | 有 2026 全量 | 导出→改一行→导入 | upsert 成功 | --- ## 三、界面测试用例(UI) **工具**:Playwright + Chrome(与项目其他模块一致)。 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | ZCZX-MYCLTB-UI-001 | 列表 | 默认加载 | UI 测试 | Playwright | §5.1 | 有数据 | 进入菜单 | 列含所属年份、**所属月份**、乡镇…;**年月筛选为空** | | ZCZX-MYCLTB-UI-002 | 列表 | 年月乡镇筛选 | UI 测试 | Playwright | §5.1 | 有数据 | 选择后搜索 | 结果正确 | | ZCZX-MYCLTB-UI-003 | 列表 | 重置 | UI 测试 | Playwright | §5.1 | 已筛选 | 点重置 | 条件清空 | | ZCZX-MYCLTB-UI-004 | 新增 | 必填校验 | UI 测试 | Playwright | §5.2 | 有 add 权限 | 不选乡镇提交 | 表单提示 | | ZCZX-MYCLTB-UI-005 | 新增 | 年份下拉 6 项 | UI 测试 | Playwright | §2.2 | 打开表单 | 查看年份下拉 | 当年起前 5 年 | | ZCZX-MYCLTB-UI-006 | 新增 | 乡镇下拉 | UI 测试 | Playwright | §2.3 | 打开表单 | 查看乡镇下拉 | 10 个乡镇 | | ZCZX-MYCLTB-UI-007 | 修改 | 回显保存 | UI 测试 | Playwright | §5.3 | 有记录 | 修改牧户数保存 | 列表更新 | | ZCZX-MYCLTB-UI-008 | 删除 | 二次确认 | UI 测试 | Playwright | §5.4 | 有记录 | 删除确认 | 行消失 | | ZCZX-MYCLTB-UI-009 | 详情 | 全字段只读 | UI 测试 | Playwright | §5.5 | 有完整数据 | 点查看 | 展示全部字段;列表未展示的项(如分龄母牛、种公牛)均可见 | | ZCZX-MYCLTB-UI-010 | 导入 | 选年月上传 | UI 测试 | Playwright | §5.6 | 有 import 权限 | 默认当前年月→上传模板 | 成功摘要 | | ZCZX-MYCLTB-UI-011 | 导入 | 未选月份 | UI 测试 | Playwright | §5.6 | 有 import 权限 | 缺月份提交 | 表单校验失败 | | ZCZX-MYCLTB-UI-012 | 权限 | 无导入按钮 | UI 测试 | Playwright | §6 | 无 import | 进入页面 | 无导入入口 | | ZCZX-MYCLTB-UI-013 | 端到端 | 导入后列表 | UI 集成 | Playwright | §4 | 空库 | 导入→筛选 2026 | 10 行乡镇数据 | | ZCZX-MYCLTB-UI-014 | 导出 | 按年月导出 | UI 测试 | Playwright | §5.7 | 有 export 权限 | 选年月导出 | 下载 `{年}年{月}月牦牛存栏数据.xlsx` | | ZCZX-MYCLTB-UI-015 | 导出 | 未选月份 | UI 测试 | Playwright | §5.7 | 有 export 权限 | 缺月份点导出 | 表单校验失败 | | ZCZX-MYCLTB-UI-016 | 权限 | 无导出按钮 | UI 测试 | Playwright | §6 | 无 export | 进入页面 | 无「按年份导出」入口 | --- ## 四、覆盖对照 | 需求章节 | 要点 | 主要用例 | | --- | --- | --- | | §2.2 年份 | 向前 5 年 | UT-001;API-012;UI-005 | | §2.3 乡镇 | sys_dept 二级 order_num>12 | UT-002;API-013;UI-006 | | §2.2.1 月份 | 1~12、非未来月 | UT-020~021 | | §5.1 列表 | 8 数据列+操作;默认不筛年月 | API-001~004、002a;UI-001~003 | | §5.2~5.4 CRUD | 必填、唯一、删除 | UT-003~006、013~014;API-006~011 | | §5.5 详情 | 全字段 | API-005;UI-009 | | §5.6 导入 | 2026年.xlsx | UT-007~012;API-014~017;UI-010~011 | | §5.7 导出 | 按年全县乡镇 | UT-018~019;API-021~025;UI-014~015 | | §6 权限 | 按钮级 | API-018~019、024;UI-012、016 | --- ## 五、修订记录 | 版本 | 说明 | | --- | --- | | 1.0 | 初版:单元 15、接口 20、UI 13;编号前缀 **ZCZX-MYCLTB** | | 1.1 | 补充 `village_dept_id` 预留字段用例 UT-016~017 | | 1.2 | 补充按年份导出用例 UT-018~019、API-021~025、UI-014~016 | | 1.3 | 补充重复导入 upsert 用例 UT-011~012 | | 1.4 | 取消逻辑删除:UT-014 改为物理删除;移除 UT-020 | | 1.5 | 按年月填报:UT-005/020~021;API-002a/014/021~022;UI 年月筛选与导出 |