测试度量体系:用数据回答"质量到底好不好"

“质量怎么样?”——测试团队被问得最多、答得最虚的问题。答"用例都过了"没意义(覆盖多少?什么级别的用例?),答"覆盖率 85%"更没意义(行数而已)。度量体系的终点不是仪表盘好看,是让"质量好不好"变成一个有数据支撑、可追踪、可归因的回答。这篇讲度量体系的完整设计:指标分层、防刷分机制、数据出口。

一、指标分层:不同角色看不同层

1
2
3
4
5
6
7
8
9
10
11
12
┌─ L0 管理层(月度,5 分钟看完)─────────────────┐
│ 质量结论:好 / 有风险 / 差(显式结论,不是数字堆)│
│ 3 个趋势线:线上缺陷率、发布成功率、MTTR │
└──────────────────────────────────────────────┘
┌─ L1 测试 leader(周度)──────────────────────┐
│ 风险敞口:遗留缺陷×严重度、flaky 率、风险覆盖率 │
│ 机制产出:门禁拦截数、灰度拦截数、左移发现占比 │
└──────────────────────────────────────────────┘
┌─ L2 一线测试/研发(每日)─────────────────────┐
│ 执行状态:今天跑了什么、红了什么、谁在等环境 │
│ 个案指标:用例 flaky 分、模块缺陷密度、我的缺陷 │
└──────────────────────────────────────────────┘

分层的原则:每层只放"该层要做的决策"对应的指标。管理层看到"用例执行次数"是噪音,一线看到"季度质量指数"是玄学——指标放错层 = 两层都没用。

二、核心指标定义(每个都有公式和陷阱)

1. 线上缺陷率(L0 核心)

1
2
3
4
5
6
定义:每万用户·天的线上缺陷数(P0+P1)
公式:线上 P0/P1 缺陷数 / (活跃用户数 × 天数) / 10000
陷阱:
❌ 用"缺陷数/版本"——版本大小不一,没法比
❌ 不区分严重度——10 个 P3 比 1 个 P0 严重?
✅ 归一化(用户·天)+ 只算 P0/P1 + 分业务线看

2. 发布成功率(L0)

1
2
3
4
5
定义:无需回滚/热修的发布占比
公式:(发布总数 - 回滚发布 - 热修发布) / 发布总数
陷阱:
❌ 只算"回滚"——"灰度中发现、未全量就停"的发布不算失败?要算(部分失败)
✅ 三态:成功 / 灰度中止 / 全量后回滚,分开统计

3. MTTR(L0,缺陷从发现到关闭)

1
2
3
4
5
6
7
8
定义:缺陷生命周期时长(按严重度分桶)
P0: 中位数目标 < 4h,P1 < 24h,P2 < 7d
陷阱:
❌ 平均数(一个挂 30 天的 P2 把均值拉爆,掩盖 P0 的恶化)
✅ 中位数 + 分位数(P90)+ 分严重度
❌ 只看"关闭时长"——把"挂着不处理"当快
✅ 拆开看:响应时长(发现→认领)+ 修复时长(认领→待验证)+ 验证时长
三段各自有 owner(响应=值班机制,修复=研发,验证=测试排期)

4. flaky 率(L1,测试系统健康度)

1
2
3
4
定义:近 7 天被判定 flaky 的用例 / 总用例
健康线 < 2%(详见 flaky 治理篇)
价值:它是"测试结果可信度"的代理指标——
flaky 率高时,L0 的所有"通过率"指标都要打折扣

5. 风险覆盖率(L1,测得值不值)

1
2
3
4
定义:被用例覆盖的风险项 / 风险清单
风险项来源:历史缺陷归因 + 架构依赖 + 本次改动 blast radius
价值:回答"这次发版的风险面测全了吗"(发版决策依据,
详见覆盖率篇/灰度篇)

6. 缺陷发现阶段分布(L1,左移成效)

1
2
3
定义:缺陷按发现阶段(评审/PR/测试/线上)的占比
价值:左移的唯一诚实成绩单(详见测试左移篇)
——"左移了多少"不靠口号靠这个分布

7. 门禁拦截率(L1,机制产出)

1
2
3
定义:被 CI 门禁拦下的问题 / 全部问题(含测试阶段发现的)
价值:证明"机器在干活"——拦截率为 0 的门禁 = 摆设
分机制看:PR 门禁 / 契约 / 灰度判据各自的拦截数

三、防刷分:度量会塑造行为(古德哈特定律)

"当一个指标变成目标,它就不再是好指标"——度量体系最大风险是被刷分。四个防刷分设计:

1. 指标成对出现(矛和盾同时看)

1
2
3
4
5
6
7
8
9
10
11
单看"用例数" → 刷用例
配对:用例数 + 单条用例平均执行时长(刷的水用例跑得飞快)

单看"通过率" → 放松断言 / 隔离真失败
配对:通过率 + 断言密度(每用例断言数)+ flaky 率

单看"缺陷数下降" → 少报缺陷
配对:缺陷数 + 线上缺陷率(内部报少了,线上会补回来)

单看"覆盖率" → 写无断言用例
配对:覆盖率 + 伪断言率(is not None 类断言占比)

原则:每个"可被刷"的指标必须配一个"刷了会受伤"的指标,两个同时看,刷分无利可图。

2. 指标只考核趋势不考核绝对值

1
2
3
4
5
❌ "覆盖率必须 85%"(达标后没人再管,跌破时找借口)
✅ "覆盖率环比不下降 + 增量 ≥ 80%"(关注变化,不给刷分终点)

❌ "缺陷数 ≤ 5"(压到 5 以下开始藏缺陷)
✅ "线上缺陷率趋势 + 内部缺陷/线上缺陷比"(内外对照)

3. 数据可下钻(防"汇报数字"和"真实数字"两张皮)

1
2
3
4
5
6
L0 的每个数字必须能下钻到 L2 个案:
管理层看到"线上缺陷率上升"
→ 下钻:哪条业务线?
→ 下钻:哪个版本引入?
→ 下钻:具体哪几个缺陷?当时的发布单/门禁记录?
任何一层下钻不通 = 上层数字是"汇报出来的"不是"跑出来的"

4. 度量数据自动采集,禁止手填

1
2
3
4
5
6
7
所有指标从系统直接取数:
缺陷数据 ← 缺陷平台 API
发布数据 ← 发布平台状态机
执行数据 ← CI 结果库
门禁拦截 ← CI 拦截日志
手填指标 = 可美化指标 = 三个月后失去信用
唯一例外:定性判断("带病发布决策是否合理")需要人填,但必须附数据引用

四、数据出口:度量不只是看板

1
2
3
4
5
6
7
8
9
10
11
12
1. 月度质量报告(L0 层,自动生成 + 测试 leader 批注)
→ 给管理层:3 个趋势 + 1 个显式结论 + 下季度风险预告
2. 周度风险清单(L1 层,自动)
→ 遗留缺陷×严重度排序、flaky 隔离区、风险覆盖缺口
→ 每项带 owner(无 owner 的风险项 = 没管理的风险)
3. 每日执行状态(L2 层,自动推送)
→ 今日常规:跑了 X,红 Y(其中 flaky Z),环境等待 W
→ 异常即推送(P0 门禁失败、flaky 率越线、超期缺陷)
4. 发版决策页(发布单的 quality 段)
→ 所有度量的"汇总结论页"(详见发布管理篇)
5. 复盘输入(缺陷归因/发布复盘/左移成效)
→ 度量数据是复盘的"事实底座",复盘结论必须引用数据

五、落地路线(3 个月)

1
2
3
4
5
6
7
8
9
10
11
12
13
M1:数据管道(最难的一步)
- 缺陷平台/CI/发布平台 API 打通,统一进指标库
- 先上 L2(每日执行状态)——一线马上有感知,信任建立最快

M2:L1 指标 + 防刷分配对
- flaky 率、风险覆盖率、门禁拦截率
- 每对指标同时上(矛和盾一起看)
- 周度风险清单自动化

M3:L0 结论化
- 月度质量报告的"显式结论"规则化(好/有风险/差 + 依据)
- 管理层第一次看到"结论 + 3 趋势"而不是 20 个数字
- 复盘流程引用度量数据(制度固化)

先 L2 后 L0 的原因:度量体系的信用来自"数据和我看到的一致"——一线先用起来发现数据靠谱,上层的结论才有人信。反过来从管理层仪表盘开始,数字对不上一次,整个体系信用破产。

六、度量体系永远不该做的三件事

不该做 为什么
用度量排名个人/团队 必然刷分 + 藏缺陷 + 拆台(数据不共享),度量考团队机制不考人
指标超过 20 个 没人看得完 = 没人看 = 没有指标。每层 ≤ 7 个,季度审视删一半
指标口径不公示 "这个数怎么算的"答不上来 = 数字没有权威。每个指标有公开公式页

七、小结

度量体系三根支柱:分层(管理层看结论、leader 看风险、一线看执行)、防刷分(指标成对、只考趋势、可下钻、自动采集)、有出口(报告/清单/发版决策/复盘,不是孤立仪表盘)。终极检验标准:三个月后问"质量怎么样",回答里每个判断都能指到一条数据,每条数据都能下钻到个案——到不了这一步,再漂亮的仪表盘都是装饰品。