测试工程与 DevOps / SRE 的边界:三方协作的真实工作流
系列专栏:测试工程师每日一博 · Day 19
上一篇:[Day 18 · 测试工程师的成长地图:从初级到资深,这五年学什么]
这是系列第二次跳脱"测试自己",回答"测试跟邻居职能怎么分地盘"。Day 18 谈"向上成长",Day 19 谈"向左右协作"。
目标:不画独占地盘,只把交叉地带的协作工程化——让三方协作靠 YAML / 接口 / playbook,而不是人情。
一、为什么必须有这一篇
工业里一个反复出现的撕裂:“这个监控告警是谁的活?”
- 测试说:“我已经把 CI 红线拉好了,告警是 SRE 的”;
- SRE 说:“告警来了只是数据,测试才知道哪些是真事故”;
- DevOps 说:“我搭了告警管道,具体怎么用是你们俩的事”。
三个职能互相推活,质量漏洞就出现在缝隙里。这一篇来把这些缝隙填上。
1.1 三职能的定位差异
先给三个职能一张定位卡,所有人必须读到一致:
| 职能 | 核心使命 | 时间维度 | 成功的标志 |
|---|---|---|---|
| 测试工程 | 把质量风险量化为业务决策 | 编码前到上线前 | “应该发现但没发现的缺陷”= 0 |
| DevOps | 让代码从开发到上线跑得快且稳 | 提交到部署 | 部署频率↑、变更失败率↓、恢复时间↓(DORA) |
| SRE | 让系统在生产里可靠 | 上线后持续 | SLO 达成率↑、错误预算未耗尽 |
注意"时间维度"那一列——三职能的核心战场时间轴互不重叠,但有交叉地带。Day 19 主要解决"交叉地带怎么分"。
1.2 工业里三个常见误解
讲清三职能定位之前,先撕掉三个反复出现的误解:
- “DevOps 就是写 CI / CD 脚本的”—— 错。DevOps 的本质是「让交付管道短而稳」,脚本只是表面动作。资深 DevOps 工程师花更多时间在 DORA 指标的优化(部署频率、变更失败率、平均恢复时间)上,而不是写 YAML;
- “SRE 就是运维的升级版”—— 错。SRE 的核心是「用工程方式解决运维问题」,从告警规则、SLO 设计到混沌实验都是工程行为。把它当"高级运维"等于浪费 SRE 一半的能力;
- “测试 = QA = 手工验收员”—— 错。这一份误解最毒。测试工程的核心是把「质量」量化、可决策(回扣 Day 18 §6.2.1 质量策略)。把它压成"点鼠标的人",你只用了测试工程师 5% 的能力。
撕掉这三个误解,后面的协作才能聊——不能把"邻居"看扁了再谈协作,那是单边独白。
二、地盘分割矩阵
把工业里常见的 12 项关键工程动作,按"谁主谁辅谁不参与"分割:
| 工程动作 | 测试 | DevOps | SRE |
|---|---|---|---|
| 单元测试 | 主 | — | — |
| 集成 / 契约测试 | 主 | — | — |
| E2E 测试 | 主 | 辅(提供 flaky 隔离环境) | 辅(给线上数据样本) |
| CI 流水线 | 辅(测试 stage) | 主 | 辅(给预生产 SLO 卡) |
| CD 流水线 | 辅(灰度门控) | 主 | 辅(灰度观察 SLO) |
| 性能压测 | 主 | 辅(跑脚本) | 辅(给生产分布数据) |
| 监控告警规则 | 辅(写"测试红灯"规则) | 辅(管道维护) | 主 |
| SLO / SLI 定义 | 辅(给"测试覆盖转 SLI"映射) | — | 主 |
| 上线发布按钮 | 辅(给"测试绿灯") | 主 | 辅(给"SLO 绿灯") |
| 回滚 | 辅(给"应回滚信号") | 辅(执行机制) | 主(决定回) |
| 故障复盘 | 辅(写红灯 case + 系统漏洞) | 辅(postmortem 平台) | 主(主持) |
| 容灾 / 混沌实验 | 辅(设计用例) | 辅(基础设施) | 主 |
读法:粗体是该动作的主责人,辅是该动作的协作角色,空是不参与。
可以一眼看出:没有任何一行只有一个职能单独干。所有 12 项都至少两个职能协作。这就是为什么"地盘大战"无解 —— 地盘本来就不是独占的,是分工的。
三、CI / CD 里的协作:测试 vs DevOps
最常见的协作场景。DevOps 主战场,测试是强势协作者。
3.1 阶段划分
开发者 push PR │ ↓ [Step 1] Pre-commit hook(lint / type check / format) │ DevOps 主 / 测试不参与 ↓ [Step 2] PR check(单测 + 覆盖率 + Pact verify) │ 测试 主 / DevOps 提供运行环境 ↓ [Step 3] Merge to main → 集成测试 + 安全扫描 + 镜像构建 │ DevOps 主 / 测试辅(集成测试) ↓ [Step 4] Deploy to staging │ DevOps 主 / 测试不参与 ↓ [Step 5] E2E 回归 + 性能基线 │ 测试 主 / DevOps 提供 flaky 隔离 runner ↓ [Step 6] 部署生产(灰度 5% → 25% → 50% → 100%) │ DevOps 主 / 测试 + SRE 给绿灯 ↓ [Step 7] 发布后观察窗(1h,看 SLO) SRE 主 / 测试不参与每一步都有清晰的 “主 / 辅” 标签。没标签的步骤,就是漏点——比如 Step 6 灰度阶段,如果测试没给"基于回归的绿灯标准",DevOps 会把"测试通过"理解为"自动化全绿",但实际可能是"自动化 200 个用例都没跑这个 canary 流量"。
3.2 一个常见冲突的解法
冲突:DevOps 想把 PR check 时间压到 5 分钟内,测试想跑全覆盖。
错误解法:互相吵架(DevOps 说"测试太慢",测试说"质量不能让步")。
正确解法:用 Day 7 的时间门控分层——
- PR check 只跑 ≤ 5 分钟的快速子集(主单测 + 关键契约);
- 每夜跑全集(全 E2E + 性能基线);
- 不让"全集绿"成为合并的硬性依赖,而是"次日修复"的节奏。
这套分层是 Day 7 已给过的工程动作。三方协作的冲突 → 用工程方式化解,不要用人情协商。
四、生产可观测性:测试 vs SRE
SRE 主战场,测试悄悄来"加测试红灯"。
4.1 监控规则里测试工程师该写的
回扣 Day 12 §4 SLO + burn rate 告警,SRE 通常负责的是"基础设施告警"(CPU、内存、QPS、5xx 率)。但测试工程师可以加一类规则:
# alerts/testing-rules.yaml — 测试工程师写的,不属于 SRE base alertsgroups:-name:testing_gatesrules:# 规则 1:已被 @Tag("prod_incident") 标记的 case 在回归里挂了# 高优告警,因为这代表历史故障复现-alert:ProdIncidentRegressionFailedexpr:ci_test_failures{tag="prod_incident"}>0for:5mlabels:{severity:critical}annotations:summary:"生产故障附件用例回归失败,可能复发历史事故"# 规则 2:契约测试 provider verify 红灯# 高优,因为 provider 部署可能被 consumer 跳版本而破坏-alert:PactProviderVerifyFailedexpr:pact_verify_status{side="provider"}== 0for:10mlabels:{severity:high}这两条规则特别:测试工程师写的告警,挂在 SRE 的告警系统里。SRE 的 oncall 看到红灯时知道是"测试视角的事故预警",不会跟"CPU 80%"那类阈值告警混在一起。
4.2 SLO 共同定义
回扣 Day 15 §3,SLO 不能只 SRE 一人写。测试工程师要贡献:
- 可用性目标:基于"测试覆盖的失败模式"反推哪些 SLI 必须达成;
- 延迟 SLI:基于"压测容量曲线"(Day 15 §5)给 P99 阈值给数据;
- 错误预算:基于"质量策略"(Day 18 §6.2.1)给消耗优先级。
也就是说,测试是 SLO 的输入侧,SRE 是 SLO 的执行侧。两边都不写就是空契约。
# slo-definition.yaml 三方共建(Day 18 §6.2.1 + Day 15 + 这一节)slo:-name:order-api-availability target:0.999# 由 SRE 写:基于生产 SLI 历史数据派生rationale_sre:"过去 90 天 5xx 率中位数 0.02%,目标 0.1%"# 由测试写:哪些测试红线对应这条 SLOrationale_test:"对应 @Tag('order_api_availability') 50 条回归 case"# 由 DevOps 写:部署频率对该 SLO 的影响rationale_devops:"每周 3 次部署,每次 0.03% 部署失败预算份额"window:30drationale_sre / rationale_test / rationale_devops三行字段是约定。每条 SLO 后面跟三个理由,三方对齐。这也是把"地盘"化为"协作"的工程动作。
五、上线 / 回滚决策:三方都参与
最热点的协作场景。出问题时三方看法往往不一致:
| 决策点 | 测试的看法 | DevOps 的看法 | SRE 的看法 |
|---|---|---|---|
| 何时该回滚 | 回归 case 持续 flaky | 部署成功率 < 95% | burn rate > 4x |
| 谁按按钮 | 不主动按 | 部署者主按 | oncall 主按(P0) |
| 回滚后干啥 | 跑 smoke test 验恢复 | 看部署日志没拖尾 | 看 SLO 回到基线 |
| 谁主导复盘 | 测试补红灯 | DevOps 改部署流程 | SRE 写时间线 |
注意"谁按按钮"那一行——按钮的主人是按场景分:
- 部署中失败(部署成功率低)→ DevOps 按钮(部署者);
- 部署后 8 小时内出问题 → SRE 按钮(oncall P0);
- 上线一周后复发历史故障 → 测试发现后报告,DevOps 按钮。
提前把"哪种场景谁按钮"写到 release playbook 里,比事后推活强 10 倍。
六、典型的"三不管"地带
工业里反复出现的责任真空:
6.1 "孤儿"测试基础设施
谁维护 selenium grid / k6 cluster / Testcontainers 镜像?
- 测试:我用,但不维护基础设施;
- DevOps:这是测试用的,我不管;
- SRE:不在我生产 KPI 里。
结果:跑了一年后镜像没人升级,有一天安全扫描扫出 CVE,所有人慌了。
解法:把它当成"二级生产系统",挂 SRE 的 SLA(<= 4h 响应),但投资改造由测试主导。
6.2 测试监控的数据源
测试告警需要 PR 历史 / CI 结果 / 测试覆盖率 —— 这些数据归谁管?
- DevOps:维护 CI,但数据出口不在职责里;
- SRE:看的是生产指标不是 CI 指标;
- 测试:用数据,但不维护存储。
结果:测试告警系统拼凑,数据延迟严重。
解法:DevOps 负责"数据出口"(webhook / API),测试负责"消费 + 告警规则"。
6.3 性能压测的"专属"环境
性能压测(Day 15)需要专属环境,不能跟 staging 共用。
- 测试:我用;
- DevOps:维护 staging,不为压测单独起;
- SRE:还是不在我生产 KPI 里。
解法:把性能环境写成 IaC(terraform),由 DevOps 主导维护,测试只是消费者。
七、协作的工程动作:CI 友好信号
协作不能只靠"我说你听"。测试工程师应该把信号发给两边:
7.1 给 DevOps 的信号(测试质量红线)
# ci-quality-gate.yamltest_quality:min_coverage:0.7max_flaky_rate:0.02pact_verify:requiredperf_baseline_drift_max:0.15# 性能回退不能 > 15%fallback_action:block_merge# 不达标 → DevOps 流水线拒绝合并这个 YAML 由测试工程师维护,但DevOps 的 CI 工程必须读取。这就是"测试质量"翻译为"DevOps 流水线行为"的接口。
7.2 给 SRE 的信号(质量红线映射 SLO)
defcoverage_to_slo_risk(coverage:dict,slo_targets:dict)->dict:""" 测试覆盖率 → SLO 风险评估 回扣 Day 18 §6.2.1:让 SRE 的告警决策能"考虑"测试盲点 """risky_areas=[]forslo,targetinslo_targets.items():# 该 SLO 关联的代码路径覆盖率cov=coverage.get(slo_to_path[slo],0)ifcov<0.5:risky_areas.append({"slo":slo,"coverage":cov,"risk":"高",# 测试盲区 → 这条 SLO 不"知道"会发生啥"recommendation":"建议把 burn rate 告警阈值从 4x 降到 2x",})returnrisky_areasSRE 看到"建议阈值降一档"的输入,会比看到"测试覆盖率 60%"有用 10 倍。翻译永远是协作的桥。
八、回扣系列
| Day | 在 Day 19 它对应 |
|---|---|
| Day 1-7 | §3 CI 协作(测试 vs DevOps) |
| Day 8 | §3 TDD 红绿是 PR check 的核心 |
| Day 9 | §7.2 Pact verify 必进 DevOps 门 |
| Day 10 | §6.1 flaky runner 维护真空 |
| Day 11 | §3.1 PR check 是左移的执行点 |
| Day 12 | §4 SLO + burn rate(SRE 主) |
| Day 13 | §7.2 LLM 报告解读成"信号" |
| Day 14 | §6.3 压测专属环境(IaC) |
| Day 15 | §4.2 SLO 三方共建(test 输入侧) |
| Day 16 | §5 上线 / 回滚决策三方 |
| Day 17 | §3 PR review 协作(测试 + 开发 + DevOps) |
| Day 18 | §1.1 三职能定位卡的成熟度 |
12 条回扣,跟 Day 16 / Day 17 同样级别的总调用。这是合情合理的——想讲清楚"地盘",必须把前 18 天的工具 / 流程 / 闭环全部重新调一次。
九、协作反模式
| 反模式 | 表现 | 后果 |
|---|---|---|
| “Venn 图思维” | 试图画出独占地盘 | 漏掉交叉地带 |
| “我用你不管” | 测试用 = 测试维护 | 测试基础设施腐烂 |
| "数据出口"模糊 | 谁出口 PR / CI 数据不明确 | 测试告警延迟 |
| 监控规则只 SRE 写 | 测试红灯不在告警系统里 | 故障复发率高 |
| 部署门控不互联 | DevOps 不知道测试质量红线 | 低质量合入 |
| “StackSize 大讨论” | 在层级深度上推诿 | 工程动作无主责 |
十、原则三句话
- 没有"独占地盘",只有"分工协作"—— 12 项关键动作至少两个职能协作;
- 协作靠"工程接口"——YAML / 文件 / API,不要靠人情协商;
- 测试给 DevOps / SRE 的价值,是"翻译"—— 把质量风险翻译为 CI 行为 / SLO 输入。
十一、思考题
留给今晚:
- 你团队的 CI 流水线,测试 / DevOps / SRE 各自主哪几个 stage?有没有重叠或真空?
- 灰度发布时,谁会按"暂停 / 回滚"按钮?这个决策有 release playbook 文档吗?
- 你的 CI 质量门控 YAML(§7.1)是谁维护?DevOps 知道它的存在吗?
- 上一次故障复盘(Day 16 §4.2 时间线),时间线由谁拼起来?是 SRE 独力 + 测试 / DevOps 在旁边看吗?
十二、TL;DR
- 三职能定位:测试(质量风险量化) / DevOps(代码到部署快稳) / SRE(生产可靠);
- 12 项关键动作的地盘分割矩阵 —没有任何一项是单职能独占;
- CI 五阶段 + 部署两阶段 + 故障五阶段都需要三方协主;
- 三个 “三不管” 地带(测试基础设施 / 测试数据出口 / 性能压测环境)需要明确归属;
- 协作靠工程接口:ci-quality-gate.yaml / SLO rationale_* / coverage_to_slo_risk 接口。
下一篇:Day 20 ·测试工程师的 OKR 与度量:把"质量"翻译为可量化指标
这是系列第 20 篇里程碑。把这一系列所有的工程动作收束为"测试团队 OKR 的指标体系" —
defect density、testability score、flaky rate、mean time to detect、contract coverage,
让"质量"成为驱动决策的数字,而不是团队内部的形容词。下篇见 👋
