---
name: l1b-business-rules-guide
description: L1b 业务规则测试的覆盖范围、推导方法和断言要求参考。
---

# L1b 业务规则测试指南

## 核心原则

L1b 测试场景**主路从业务流程正向推导**，bug 暴露的边界条件作为补漏放在独立的 `describe('回归测试')` 块中。

- ✅ 主路：从 `01-prd.md` + `04-state-machine.md` 推导所有业务规则 → 形成测试场景骨架
- ✅ 回归补漏：实际 bug 揭示的"PRD 没写但实际重要"的边界条件，单独放在 `describe('回归测试')` 中
- ❌ 反模式：把 bug 倒推的测试混进业务规则主路 describe，导致测试场景结构被历史 bug 污染

bug 不是不能用——它常常是"未被文档化的隐式规则"的信号，但应当作为**补漏来源**而非**主路来源**。

## 推导方法

1. 阅读 `01-prd.md` 和 `04-state-machine.md`，列出所有业务规则
2. 按业务流程阶段分组（目标设定 → 评估 → 校准 → 结果确认）
3. 每条规则至少有一个测试场景，断言按"业务关键字段精确值 + 元数据字段存在性"分级（详见下文"断言要求"）
4. bug 揭示的边界条件作为回归测试单独放 `describe('回归测试')` 块中，不混入业务规则主路

## 按阶段覆盖

### 目标设定阶段
- KPI 创建：员工创建 KPI → 状态为 DRAFT
- KPI 提交：权重之和 = 100 时可提交，≠ 100 时拒绝
- KPI 审批：主管审批后状态变为 APPROVED
- KPI 驳回：驳回后状态回到 DRAFT，员工可修改后重新提交
- 依赖管理：设置依赖人 → 依赖人确认 → 依赖状态更新

### 评估阶段
- 自评：员工提交自评分和自评评语 → 状态变为 SELF_EVALUATED
- 主管评：主管提交评分和评语 → 状态变为 MANAGER_EVALUATED
- 360 评估：添加评估人 → 所有人提交 → 自动 COMPLETED
- 加权分计算：Σ(分数 × 权重) / Σ权重 = 精确值（验证 Decimal 类型安全）

### 校准阶段
- 等级分布：从 KPI 评估数据自动计算等级
- 校准调整：修改等级 → 保存 → 数据刷新
- 无 performanceResult 时：从 KPI 评估反算

### 结果发布阶段
- 绩效结果生成：进入 CONFIRMING 后员工能查到结果
- 员工确认/申诉：确认后 confirmStatus 变更

### 跨阶段规则
- 数据隔离：创建 2 个组织 → 查询只返回目标组织数据
- 状态机完整性：周期 DRAFT → GOAL_SETTING → ... → COMPLETED，不能跳步
- 级联影响：修改已提交 KPI → 整体提交状态撤回

## 断言要求（分级）

**业务关键字段：必须精确值断言**
- 状态字段：`expect(data.status).toBe('APPROVED')`
- 计算结果：`expect(data.totalScore).toBe(80)`、`expect(data.weightedAvg).toBeCloseTo(75.5, 1)`
- 业务标志：`expect(data.canEdit).toBe(true)`
- 关键关联：`expect(data.organizationId).toBe(targetOrgId)`
- ❌ 反模式：`expect(data.totalScore).toBeDefined()`（业务字段用存在性断言无意义）

**元数据字段：存在性 + 类型断言即可**
- `id` / `createdAt` / `updatedAt` 等自动生成字段：`expect(data.id).toMatch(/^[\w-]+$/)`、`expect(typeof data.createdAt).toBe('string')`
- 不要硬断 `expect(data.id).toBe('xxx')` 或 `expect(data.createdAt).toBe('2026-04-28T...')`，会导致测试脆弱

**结构断言（适用于响应形状）**
- 列表 API：`expect(Array.isArray(data.items)).toBe(true)` + 关键业务字段精确断言
- 分页：`expect(data.total).toBeGreaterThanOrEqual(N)` 或精确 `toBe(N)`（视场景）

**其他规则**
- 状态机测试必须连续执行全流程，不能只测单步
- 多组织场景必须创建 2 个组织，验证查询结果只含目标组织数据

## 通用覆盖（L1a + L1b 共用）

- 修改已有数据的级联影响（修改已提交记录后关联状态是否正确回退）
- 组织隔离：所有列表/查询 API 传 organizationId 后是否只返回该组织的数据
- 跨域业务链路：模块 A 的操作触发模块 B 的状态变更是否生效
- 请求体必须用前端实际字段名（从 `services/api/*.ts` 确认）
- 测试数据质量校验：种子数据完整性、JSONB 内部结构
- 响应字段名验证：断言字段名与前端 interface 一致
- 计算结果断言：加权分必须有精确数值断言
- 权限种子验证：Employee 不能访问 admin 类端点
