Files
lingxi/docs/工程规范/06-测试与CI规范.md
T
Stev_Wang dd01b89214
ci / 质量门禁 (push) Canceled after 0s
docs(docs): 调整分支策略为仅 main 直推
背景:用户确认仓库只保留 main,不再创建任何远程分支或走 PR 合并。

改动:
- 01-Git规范 V1.1:仅 main 直推,禁止非 main 分支推送、force push 与 Merge commit;
- AGENTS V1.1:变更流程改为直接提交并推送 main;
- 07-CodeReview:PR 模板改为提交说明,合并流程改为推送与推送后观察;
- 03/06/工程规范 README 同步去除 PR 措辞;
- CI 仅保留 push main 与 workflow_dispatch 触发。

影响面:仅流程与文档,无代码/数据/接口变更。
回滚方式:git revert 本提交即可恢复旧流程。
验证:format:check、lint、typecheck 全绿(10/10)。
2026-11-02 17:40:01 +08:00

121 lines
5.3 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 06 · 测试与 CI 规范
| 项 | 内容 |
| --- | --- |
| 文档版本 | V1.0(2026-11-02) |
| 依据 | 技术架构 §10.4(测试策略)、§4.6(CI/CD)、§4.1.1(本地环境) |
| 适用范围 | 全仓库 |
| 强制级别 | 强制 |
---
## 1 测试分层
| 层级 | 工具 | 范围 | 运行时机 |
| --- | --- | --- | --- |
| 单元 | Vitest | Service、工具函数、状态机、命名 / 表单引擎 | 每次提交(CI + 本地) |
| 集成 | Vitest + Testcontainers(PG 18 / Redis 7.4 / MinIO) | Repository、队列、迁移、事务 | 每次 push `main`(CI) |
| 契约 | OpenAPI + `oasdiff` | 接口兼容性 | 每次 push `main` |
| E2E | Playwright | 主链路(登录 → 生成 → 预览 → 勾选 → 导出) | 主干 + 发布前 |
| 性能 | k6 | 列表 / 任务提交 / SSE | 发布前(仅 staging) |
| 视觉回归 | 图片像素比对 | PSD 合成产物 | 改动 `packages/render` 时 |
- `TST-01` 单测与源码同目录,命名 `<name>.spec.ts`;集成 `*.int.spec.ts`;E2E 放 `e2e/`。
- `TST-02` 关键包(`shared` / `form-engine` / `render` / `ai-sdk`)行覆盖率 **≥ 70%**;整体基线只升不降。
- `TST-03` 禁止提交 `.skip` / `.only`;CI 检测到即失败。
- `TST-04` 禁止依赖执行顺序;每个测试自建数据、自清理(用独立 `customer_id` 前缀)。
---
## 2 必测清单(缺一项即 Review 不通过)
| 编号 | 场景 |
| --- | --- |
| `TST-05` | **权限三态**:每个端点至少「有权限 / 无权限 / 范围外」3 条用例 |
| `TST-06` | **客户隔离**:跨客户读取必须 403 或空集,且不得泄漏存在性 |
| `TST-07` | **状态机**:合法迁移 + 非法迁移(返回 409)各一条 |
| `TST-08` | **幂等**:同 `Idempotency-Key` 重复提交只产生一次副作用 |
| `TST-09` | **成本前置**:任务提交未带预估成本 / 超预算时被拒 |
| `TST-10` | **审计**:导出、权限变更、AI 配置变更均落审计 |
| `TST-11` | **降级路径**:抠图失败 → 原图 + `low_quality` 标记;AI 内容违规 → 不重试 |
| `TST-12` | **迁移**:升级后可回滚;expand 阶段旧代码仍可用 |
| `TST-13` | **任务断点**:SSE 断线后 `Last-Event-ID` 可续推 |
| `TST-14` | **命名规则**:非法字符、超长、同名重名各一条(PRD R-01) |
---
## 3 测试数据与环境
- `TST-15` 禁止连接生产库 / 生产对象存储;CI 用 Testcontainers 起同版本依赖。
- `TST-16` 测试数据用 factory 构造,禁止依赖线上导出数据。
- `TST-17` 测试内置时钟可注入(`clock` 包),禁止 `new Date()` 直接断言时间。
- `TST-18` AI 调用在测试中一律 mock Provider,**禁止**真实外网调用(防止费用与不稳定)。
- `TST-19` 涉及文件的测试用内存 / 临时目录,结束后清理。
---
## 4 CI 流水线
```
install --frozen-lockfile
→ format:check → lint --max-warnings=0 → typecheck
→ unit test(coverage)→ build
→ integration(Testcontainers)→ openapi:diff
→ e2e(main)→ 镜像构建 + 漏洞扫描
```
| 阶段 | 阻断条件 |
| --- | --- |
| 安装 | lock 文件与 `package.json` 不一致 |
| 格式 / Lint | 任一错误或警告 |
| 类型 | 任一错误 |
| 单测 | 失败或覆盖率低于基线 |
| 集成 | 失败或超时(单测总时长 ≤ 10 分钟) |
| 契约 | `oasdiff` 检出破坏性变更但未升版本 |
| 构建 | 失败 |
| 安全 | 高危漏洞 > 0 |
- `TST-20` 流水线并行化按包拆分(Turborepo),但门禁结论必须在聚合 job 上判定。
- `TST-21` 禁止通过 `--passWithNoTests`、跳过集成测试等方式「修绿」;豁免须技术负责人批准并留提交说明记录。
- `TST-22` flaky 测试 24 小时内修复或移除并登记,**禁止**重试 3 次掩盖。
---
## 5 特性开关与灰度
| 变量 | 用途 |
| --- | --- |
| `FEATURE_VIDEO` | 视频线开关(未完成不得外露) |
| 其他 `FEATURE_*` | 按里程碑临时开关,上线稳定后删除 |
- `TST-23` 未完成功能必须藏在开关后,**禁止**半成品直接可见。
- `TST-24` 开关必须有默认值、有 owner、有清理期限(写进提交说明或配置注释)。
- `TST-25` 开关组合不得导致数据不一致(关闭后已产生的数据仍可读)。
---
## 6 发布与回滚
```
staging 部署 → 冒烟(登录 / 生成 / 预览 / 导出)
→ 生产迁移(expand)→ 灰度 10% → 观察 30 分钟 → 全量 → 收缩(contract,下个版本)
```
- `TST-26` 迁移先行、代码后行;收缩步骤必须在**确认无旧版本流量**后执行。
- `TST-27` 每次发布必须有回滚预案:代码回滚 + 数据回滚(或前向修复)分别说明。
- `TST-28` 发布后观察:错误率、P95、队列积压、AI 费用;异常 15 分钟内决策回滚。
- `TST-29` 发布记录写入 `docs/releases/`(版本、变更、影响面、回滚方式)。
---
## 7 检查清单
- [ ] 新增 / 修改逻辑有对应单测,关键包覆盖率达标
- [ ] 端点有权限三态用例,客户隔离用例存在
- [ ] 状态机非法迁移、幂等、成本前置已覆盖
- [ ] 集成测试用 Testcontainers,无外网依赖
- [ ] CI 全绿且未使用豁免
- [ ] 迁移可回滚,staging 已演练
- [ ] 未完成功能藏开关,开关有清理期限
- [ ] 发布记录与回滚预案已写