# Pm Test Cases

> 用户要求生成、撰写或创建测试用例时必须使用本技能。 触发场景：(1) "生成测试用例" "写测试用例" "创建测试用例", (2) "QA测试" "测试文档" "验收标准" "测试计划", (3) "导出测试用例" "测试用例导出Word" "测试文档转Word", (4) 从需求生成功能/边界/异常/权限测试用例， (5) 生成 API 测试用例或测试报告模板。 基于需求文档或功能描述自动生成完整测试用例集。

- Skill: `idwong/pm-test-cases` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add idwong/pm-test-cases`
- Raw SKILL.md: https://api.skillmd.com/api/skills/idwong/pm-test-cases/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: iDWong (https://skillmd.com/u/idwong)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/idwong/pm-test-cases

---


> **流程位置**：`pm-master` 阶段9 测试用例 ／ `dev-master` **阶段9 测试**；也可单点直接调用。
> （两条流程的阶段号不同，按当前在跑的那条读。）
> 流程内落盘路径 `prd/test/{日期}-{项目}-测试用例-V{版本}.md`（流程门禁按 glob 匹配，命名带产品名/日期是正常的）。
> 上游读 `SPEC_SOURCE`（SRS/PRD），与 `pm-ai-ship-audit` 的 `derive-tests` 覆盖地图对齐（`dev-master` 阶段11；`pm-master` 已无审计阶段）。

# 测试用例生成器

## 角色定义

以资深测试工程师视角工作：
- ✅ 测试用例覆盖业务功能、异常、性能、权限四个维度
- ✅ 预期结果必须具体明确，不能写"显示正确"、"操作成功"
- ✅ 异常测试覆盖所有必填字段、格式校验、关联数据约束
- ❌ 不只测试正常流程，不忽略边界条件
- ❌ 不遗漏关键业务场景（删除已关联数据、重复提交等）

详细的表格规范和覆盖场景参考：`references/test-cases-guide.md`

## 执行流程

### Step 0: 扫描项目上下文

先主动扫描项目，找到已有文档再开始工作：

| 优先级 | 文件类型 | 查找方式 |
|--------|---------|---------|
| 最高 | 需求说明书 | `Glob("**/*需求*说明书*.md")` |
| 高 | 功能清单 | `Glob("**/*功能*清单*.md")` |
| 低 | 路由/代码 | `src/router/`, `src/views/`, `src/api/` |

默认全量覆盖所有找到的功能模块，只有文档完全缺失时才询问用户。

### Step 1: 读取模板

读取 `references/templates/test-cases.md`，按模板结构生成文档。

### Step 2: 生成任务清单

**必须先展示任务清单，再逐个生成，禁止一次性写入整个文档。**

任务拆分原则：**拆到最小粒度，每个功能模块的每类测试（业务功能、异常、性能、权限）都是独立任务。**

任务清单示例：
```
| 序号 | 任务名称 | 状态 |
|------|---------|------|
| 1  | 创建文档骨架 | ⏳ 等待中 |
| 2  | 6.1.1 设备档案 - 业务功能测试 | ⏳ 等待中 |
| 3  | 6.1.1 设备档案 - 异常测试 | ⏳ 等待中 |
| 4  | 6.1.1 设备档案 - 性能测试 | ⏳ 等待中 |
| 5  | 6.1.1 设备档案 - 权限测试 | ⏳ 等待中 |
| 6  | 6.1.2 设备分类 - 业务功能测试 | ⏳ 等待中 |
| 7  | 6.1.2 设备分类 - 异常测试 | ⏳ 等待中 |
...
| N  | 七、测试总结 | ⏳ 等待中 |
```

执行规则：
1. 每次只生成一个任务，生成前更新为 🔄，完成后更新为 ✅，重新展示清单
2. 任务1（文档骨架）用 Write 创建文件，后续用 Edit 追加
3. 每条用例使用卡片式表格（`^` 合并语法），格式参考 `references/test-cases-guide.md`

### Step 3: 质量检查

生成完成后自检：
- [ ] 每条用例的预期结果具体明确
- [ ] 每个必填字段都有"为空"的异常测试
- [ ] 每个有权限控制的功能都有权限测试
- [ ] 删除/修改操作都有"二次确认"验证
- [ ] 用例编号无重复

### Step 4: 导出文档（可选）

> **⚠️ 导出前后各一件事**：① 图片必须放在**文档同级的 `images/` 子目录**且**文件名纯 ASCII**——这是唯一可用形式，`img/`、`images/sub/`、`../images/`、与文档同目录、中文名**全都静默丢图**（脚本仍打印 `Export succeeded`，但 `word/media/` 是空的）；② 导出后立刻验 `unzip -l <docx> | grep -c "word/media/"`，数字必须等于图片张数。实测边界表见 `../common/README.md`。

**Windows（PowerShell）：** `../common/export-word.ps1 <markdown文件路径> test-cases`

**跨平台：** `python ../common/export-word.py <markdown文件路径> test-cases`

**Git Bash：** `bash ../common/export-word.sh <markdown文件路径> test-cases`

## 文档命名规范

`prd/test/{日期}-{项目名称}-测试用例-V{版本号}.md`

示例：`prd/test/20260330-智慧厂区巡检系统-测试用例-V1.0.md`（研发链跑同一技能时落 `dev/test/`）

**修订：就地改也要改文件名。** **不论体量大小一律就地 `Edit` 改**（大文档尤其别整份重写，小文档也不要另存新文件）——**目录里永远只留最高版本那一份**；改完必须三样一起动——文首「文档版本」、版本记录表、**`mv` 把文件名的版本号也改掉**（局部修订 `+0.1`，结构性重写进大版本；日期取改动当天）。**绝不允许内容已是 V1.1、文件名还写 V1.0。**改名后 `grep` 一遍旧名，把 README 清单、下游「来源」行、`tools/` 脚本里的引用一并改掉。完整规则见 `../common/README.md`。

## 参考资源

- 测试用例模板：`references/templates/test-cases.md`
- 表格规范和覆盖场景：`references/test-cases-guide.md`

## 输入来源：设计稿也是合法输入

主真源仍是 SRS / PRD。但项目若已有**过了闭环检查**的设计稿（`design-system/`），**必须一并读**——
它能补出文档里没有的两类用例，漏读等于少一半覆盖：

| 读什么 | 能多出什么用例 |
| --- | --- |
| `FLOWS.md` | 每条流程的**失败与取消分支**（文档常只写好天气那条）、中间态（loading / 遮罩 / Toast）|
| `HANDOFF.md` 第 4 节状态矩阵 | 七态逐页覆盖：空 / 加载 / 错误 / 无权限 / 部分字段缺失 / 超长超多数据 |
| `HANDOFF.md` 第 5 节 | 表单校验的**正则、触发时机、错误文案**——边界用例照它写，不要自己编 |
| `CONSISTENCY.md` | 多端项目的差异点，按端各出一组用例 |

**设计稿与 SRS 冲突时取 SRS**，并在用例的「备注」列记一行差异，别闷着按设计稿写。

### 真源里有状态机表时，逐行转成用例（最容易漏的一类）

SRS／PRD 里若有**业务对象状态机表**（订单、审核、退款、工单、提现、内容发布；
PRD 侧见 `pm-prd-spec` 的 T14，SRS 侧在 2.4 业务流程图与各 3.5.x「状态与权限说明」），
**逐行生成两类用例**，一行都不能跳：

| 从哪一列来 | 出什么用例 | 例 |
| --- | --- | --- |
| 当前状态 + 触发事件 + 新状态 | **正向流转用例**：在该状态下执行该事件，断言状态变为新状态 | 待审批单据点【通过】→ 状态变「已通过」 |
| 副作用列 | **副作用断言**（并到上面那条里，不单独成条）：数据变化、通知是否发出 | 通过后 1 分钟内自动入账、短信已发出、流水已写入 |
| **「此状态下不允许的操作」列** | **非法操作拦截用例**——每个不允许的操作各一条 | 对「已入账」单据调编辑接口 → 拒绝并提示，余额不变 |
| 超时/系统自动流转行 | **时效用例**：把时间推到阈值后，断言自动流转与通知 | 待审批满 72 小时 → 自动「已过期」，通知提交人 |

- **非法操作拦截那一类最容易整块漏**，而它正是线上事故高发区（绕过界面直接调接口改已完结的单据）。
  它属于「权限测试」还是「异常测试」不重要，**关键是别因为界面上点不到就不写**。
- 状态机里的**每个状态至少被一条用例覆盖到**，终态要验证"确实不能再流转"。
- 表里没有的流转要**当成缺陷提出来**（"驳回后能否重新提交"没写），不要自己假设一个补上。

## 外部依赖与降级：Word/xlsx 导出

导出链走**技能库根的 `config.json`** 里的 `apiBaseUrl`（**端点不随仓库分发**，取值见该文件）。

| 情况 | 表现 | 怎么办 |
|---|---|---|
| 没配 `config.json` | 脚本报「无法从 config.json 读取 apiBaseUrl」 | 从同级 `config.example.json` 复制后填地址 |
| 服务没起 | `curl` 连不上 / 超时 | 先自检（在技能自己的目录下跑）：`curl -s -o /dev/null -w '%{http_code}' "$(python3 -c 'import json;print(json.load(open("../config.json"))["apiBaseUrl"])')/"`，**连得上就行**（`/` 不是路由，返回 404 也算通；连不上才是服务没起），起服务后重试 |
| 两者都缺 | —— | **降级交 md**，并在交付清单里写明「Word 未导出（端点未配）」 |

**三条不许**：不许把「导出失败」写成完成；不许跳过导出直接说交付完成；
不许在导出后不验图——`unzip -l x.docx | grep -c 'word/media/'` 要等于文档里的图片张数（文件名含中文会静默丢图）。

