项目尚无统一工程规范,AI 助手与研发各自发挥导致返工风险。建立 总纲 + 细则两层结构:AGENTS.md 只写硬约束与索引(14 条红线、技术栈 基线、仓库结构、命令契约),细则拆为 10 份文档覆盖 Git、代码风格、 格式化、API 与路由、数据库、测试与 CI、Review、日志、密钥、资产命名。 影响面:仅文档。约束力从本轮起对新建代码生效;与现状冲突处以文档为准。 回滚方式:git revert 本提交。
5.3 KiB
5.3 KiB
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、队列、迁移、事务 | 每次 PR(CI) |
| 契约 | OpenAPI + oasdiff |
接口兼容性 | 每次 PR |
| 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-18AI 调用在测试中一律 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、跳过集成测试等方式「修绿」;豁免须技术负责人批准并留 PR 记录。TST-22flaky 测试 24 小时内修复或移除并登记,禁止重试 3 次掩盖。
5 特性开关与灰度
| 变量 | 用途 |
|---|---|
FEATURE_VIDEO |
视频线开关(未完成不得外露) |
其他 FEATURE_* |
按里程碑临时开关,上线稳定后删除 |
TST-23未完成功能必须藏在开关后,禁止半成品直接可见。TST-24开关必须有默认值、有 owner、有清理期限(写进 PR 或配置注释)。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 已演练
- 未完成功能藏开关,开关有清理期限
- 发布记录与回滚预案已写