# 状态机驱动组织方法（state-machine）

> 被测功能有**明显状态流转**时的用例组织方法（何时选它见 `../testing-principles.md` 第 2 节）。状态机驱动能发现更多遗漏的边界场景。

## 1. 提取状态机

从需求/技术方案/代码中提取核心状态机，逐项确认：

```text
状态集：{待领取、标注中、已提交、已通过、已驳回、已过期}
事件集：{领取、提交、通过、驳回、超时}
转换边：状态A --事件--> 状态B（逐条列出，含守卫条件）
```

- 每条边必须有依据（文档章节或 `文件:行`，按 `../evidence.md` 标注）
- 代码模式下从代码的状态字段与分支提取**实际**状态机，与文档状态机对照——缺失的边、多出的边都是发现（文档偏离 / 死代码）
- 状态机图以文字清单落盘（`状态A --事件--> 状态B` 一行一条），不要求画图

## 2. 按状态节点分模块

每个状态节点一个模块，模块内覆盖四类内容：

1. **进入条件**：什么操作/事件让对象进入此状态（含从哪些状态可以到达）
2. **操作行为**：此状态下允许的操作、可见的数据、界面表现
3. **转换规则**：此状态下每个事件触发后转向哪里；守卫条件（如"仅管理员可驳回"）
4. **异常情况**：非法事件（此状态下不允许的操作）、超时、并发冲突

## 3. 每条边一个用例 + 三类必补场景

- 一阶主干：**每条状态边至少一条用例**（`A --事件--> B`：处于 A、触发事件、断言到 B 且伴随现象正确）
- **非法转换**：此状态下触发不允许的事件 → 断言拒绝且状态不变
- **并发/竞态**：两个操作同时作用于同一对象（如管理员驳回的同时标注员提交）→ 断言状态一致、无中间态泄漏
- **逆向边**：有回退/撤销语义的边（已提交 → 驳回 → 重新编辑）单独成用例，重点验证回退后数据是否保留/重置

## 4. 横切关注点独立模块

权限（谁能触发哪些事件）、通知（哪些边触发消息）、数据一致性（状态变更时关联数据级联）作为独立模块补充，不混入状态模块。

## 5. 何时不用状态机组织

无明显状态流转的功能（纯输入校验、查询、数据转换）按 `boundary.md` / `data-driven.md` 组织，不要硬造状态机。
