1643 字
约 5 分钟
10
S16-A02 · 质量门禁与发布:测试策略、灰度与回滚验收
2024-12-31
2026-11-07

适用读者:要对"能不能发"负责的人(技术负责人、发布 owner)。
前置:S16-B04(E2E)、S16-A01(可观测性)、S17(服务发布)。
覆盖旧文:—(E 驱动)。方法论旁证:A-275 的"审查反馈提升"(把评审意见转成可执行规则)。
扩展点:E-S16-010(门禁阈值)、E-S16-011(回滚验收三条件)。
上一篇:S16-A01 · 可观测性架构:采样、成本、保留与故障域
下一篇:S16-X01 · 书目与工具清单。


1. 一句话结论

门禁不是"测试全绿",而是"每一类风险都有一个可自动判定的证据"。 覆盖率是必要但不充分的条件:它能挡住"没测",挡不住"测错"。

门禁写法 挡住什么 挡不住什么
行覆盖率 ≥ 60% 大面积未测 断言恒真、mock 掉真实依赖
分支覆盖率 ≥ 50%(核心模块) 未走的分支 跨组件契约
主干 E2E 全绿 系统级断裂 边界数据
架构规则脚本 依赖方向违规 设计不合理
性能基线不回退 > 10% 性能劣化 容量上限

2. 门禁阈值:怎么定才不反噬(E-S16-010)

原则 说明 反例
分层设阈值 核心域(计费/库存)高,边缘模块低 全仓库统一 80% → 大量无意义断言
新增代码优先 对 diff 覆盖率设阈值(如新代码 ≥ 70%),存量不追溯 一次性给遗留代码补测试 → 造假
门禁必须可在 10 分钟内跑完 超过就被绕过 全量 E2E 进每个 PR
门禁失败必须给"怎么办" 报错指向规则与修复建议 只贴一堆红叉
# 示例:分层门禁(CI 片段,示意)
gates:
  unit:        { branch_coverage: 50, fail_on: new_code_below: 70 }
  integration: { suites: ["*IT"], timeout: 10m }
  e2e:         { suites: ["e2e/smoke"], timeout: 15m }   # 只在合并主干前跑
  arch:        { script: "tools/check-arch-rules.ts", fail_on: violation }
  perf:        { baseline: "p95.json", max_regression: "10%" }

判据:这套门禁在过去 3 个月挡住过几次真实缺陷? 一次都没挡 → 门禁是装饰。


3. 把评审意见转成规则(A-275 的"审查反馈提升")

原文的闭环是:人工评审发现的问题 → 能不能变成一条自动检查?

评审意见 可规则化? 落地
"渲染进程不能直接调 Node API" ✅ 静态检查脚本(B04 §3)
"这里要加超时" ✅(部分) 静态规则:HTTP 客户端必须设置 timeout
"异常要打日志" ✅(部分) 规则:catch 块内必须有 log.*
"这个设计不合理" ❌ 只能靠 ADR/评审

频率判据:同一类评审意见出现 3 次 → 就该写成规则;只出现 1 次 → 保持人工。


4. 灰度与回滚验收(E-S16-011)

4.1 灰度节奏(以 1% → 5% → 25% → 100% 为例)

阶段 观察窗口 放行条件 停止条件
1% 30 分钟 错误率与基线持平、P95 不回退 > 5% 任一指标超阈值
5% 1 小时 同上 + 无新增告警类型 同上
25% 2 小时 同上 + 下游依赖无异常 同上
100% 24 小时 SLO 达标 触发回滚

4.2 回滚验收三条件

# 条件 判定方式
① 可回 上一版本镜像/配置可用,且已验证可启动 预发跑过一次回滚演练
② 回得去 数据/消息兼容(无不可逆 schema 变更;消息可被旧版本消费) 契约测试 + 双写/兼容窗口
③ 回得快 从决策到恢复 < 目标 MTTR(如 5 分钟) 自动化脚本 + 权限预置

判据:没演练过的回滚等于没有回滚。 每条发布单上写清"回滚命令是什么、谁有权限、预计多久"。

4.3 不可逆变更的例外处理

变更 风险 处理
删列/改类型 旧版本读不到 三步走:加新列双写 → 切读 → 删旧列(隔一个版本)
消息格式变更 旧消费者解析失败 加版本字段,消费者兼容双格式
缓存 key 变更 冷启动击穿 预热 + 限流 + 降级

5. 发布单模板(可直接抄)

# 发布单:order-service v1.8.0
## 变更范围
- 新增:库存预占接口(幂等键 = 订单号)
- 修改:支付超时 3s → 5s
## 证据
- [x] 单测:分支 58%,新代码 74%
- [x] 集成:*IT 全绿(Testcontainers MySQL 8.4)
- [x] E2E:smoke 3 条(下单/支付/查询)
- [x] 架构规则:通过
- [x] 性能:P95 与基线持平(±3%)
## 观测
- 关键指标:order_create_p95、payment_timeout_rate
- 告警:错误率 > 1% 或 P95 > 800ms 立即停止放量
## 回滚
- 命令:kubectl rollout undo deploy/order-service
- 数据兼容:本次无 schema 变更
- 演练:2026-10-28 预发已演练,恢复耗时 2m10s

6. 常见误区

误区 纠正
"覆盖率越高越安全" 覆盖率只证明"执行过",见 §1 表
"灰度就是随机放量" 灰度要有观察窗口 + 停止条件,否则只是"提前上线"
"回滚就是把镜像换回去" 还有数据兼容与消息兼容(§4.2 ②)
"门禁越严越好" 过严 → 被绕过;门禁必须"快、准、有指引"

7. 自测

  1. 你的发布单里,"回滚"一栏写的是命令,还是"回滚即可"?
  2. 上一次回滚演练是什么时候?没演练过 → 条件 ① 不成立。
  3. 你的门禁在过去 3 个月挡住过几次缺陷?写不出 → 门禁需要重设。

8. 下一篇

S16-X01 · 测试与可观测性书目/工具清单 —— 把 A-1881 的测试书单按"读法"重组:什么时候读哪本、读到什么程度算够。

S16-A02 · 质量门禁与发布:测试策略、灰度与回滚验收
https://www.clxhxhhr.top/posts/5415/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。