SEO 摘要: 本文介绍如何通过 CI/CD 测试分层,在保障代码安全和客户体验的同时提升开发速度。文章重点讨论持续集成、持续交付、合并前测试、合并后测试、回归测试流水线、端到端测试、测试不稳定治理、测试归属、告警分诊和开发者反馈循环等实践,帮助团队构建更可靠、更高效的测试与部署流程。

这是一个关于社会技术工作流持续演进的故事:通过重新设计测试分层、告警机制和故障分诊流程,团队提升了开发速度,也重新定义了可靠测试与部署流程。
2021 年,某协作平台改变了主单体仓库 Web 应用的开发者测试流程:从过去以合并前测试为主,转向合并后多层测试。这一变化重新定义了团队对“安全性”的理解,也改变了开发人员在测试与部署之间的工作方式。
在这个项目中,团队的目标是:确保持续向客户交付频繁、可靠且高质量的版本,从而带来更简单、更愉悦、更高效的产品体验。
当你发现一行代码改动竟然会触发成千上万个测试时,该怎么办?如果其中许多测试还是令人沮丧的端到端测试,执行着与你的改动无关的复杂工作流,并且运行极不稳定,又该如何处理?如何安全地重构一个主要由端到端测试组成的开发流程?
由于多年来在主单体代码库 Web 应用中遇到的问题越来越多,工程师们开始认真思考这些问题。这个 Web 应用包含平台的核心应用逻辑,由后端 API、异步任务队列和前端客户端共同组成,支撑主要用户体验。
2020 年,开发者生产力指标进一步验证了这些挫败感:
- 每次提交的测试反馈时间 p95 始终超过 30 分钟。该指标衡量的是工程师将代码提交推送到代码库,到测试执行完成之间的时间。
- 每个拉取请求的测试不稳定率始终在 50% 左右。该指标衡量的是一个拉取请求中所有提交里,是否出现过任意一个不稳定测试。所谓不稳定测试,是指对同一段代码重复运行测试时,结果可能不同。
2021 年初,多个团队的工程师启动了一个项目,希望通过改造测试流程来回答这些问题。本文将介绍团队如何设计一系列技术和组织层面的变化,让 Web 应用测试变得更简单、更快速、更可靠。
对于企业研发团队而言,CI/CD 测试分层并不只是测试平台的局部优化,而是会影响目标拆解、需求评审、开发实现、测试验证、发布上线和知识沉淀的完整研发链路。借助 PingCode 这类智能化研发管理工具,团队可以将目标、需求、开发、测试、发布、缺陷追踪和 Wiki 经验沉淀串联起来,并打通研发工具链,让测试分层带来的效率提升能够持续沉淀和复盘。
通过引入独立测试流程和上下文告警,Web 应用工程开发速度在不牺牲安全性的前提下显著提升:
- 测试反馈时间 p95 缩短了 40% 以上。如今该指标持续低于 18 分钟,并且可预测性明显提高。
- 每个拉取请求的测试不稳定率降低了 90% 以上。如今该指标稳定低于 5%。
- 根据客户报告,缺陷率没有明显增加。
问题背景:CI/CD 测试规模增长带来的挑战
在核心开发工程部门中,团队需要为开发人员提供安全、高效地构建、测试、部署和发布变更的能力,同时还要确保用户获得良好的产品体验。
团队重点关注的问题,是如何扩展持续集成和持续部署测试的基础设施,以及配套的人类工作流程。
某协作平台在 2017 年开始在 Web 应用代码库中引入自动化测试。此后三年,该代码库的测试执行次数每月增长约 10%。
工程师确保代码质量的一种方法,是在持续集成流程中,在代码合并之前运行大部分测试。也就是说,提交代码后,系统会先将变更与主线代码结合起来进行测试。如果其中任何一个测试失败,开发人员就无法合并代码。这类测试通常被称为阻塞测试。
只有当所有测试通过,并且代码完成评审后,开发人员才能合并拉取请求。合并之后,持续交付流程中还会运行最后一组测试,用于验证核心功能,例如发送消息等基本体验。
到 2020 年高峰期,团队每天会执行约一百万套测试套件,每套测试套件最多包含 4 万个测试用例。同样是在 2020 年,这些测试大多会在合并到主线之前执行,而且其中很大一部分是端到端测试。
由于端到端测试套件依赖持续集成基础设施中的许多不同组件,它们有时会变得不稳定。所谓不稳定,是指这些测试有时无法针对同一段被测代码产生相同结果。
端到端测试套件不稳定的原因很多,包括:
- 测试本身存在问题。例如,自动化测试运行框架可能因为平台自身问题而超时,或者因为重试次数过多而超时。
- 被测应用、被测系统,以及测试框架依赖的服务和库不可用。
- 被测系统和测试框架依赖的操作系统、硬件和网络出现问题,例如域名解析中断。
Web 应用代码库中几乎所有测试都是自动化的。产品工程师和测试工程师需要为每个功能编写自动化测试。这些工程师不仅要管理测试本身,还要管理支撑这些测试的基础设施,以及运行共享开发环境所需的各种后端服务。
因此,工程师经常会遇到与自己拉取请求无关的测试失败。这些失败会阻止他们合并代码,并造成测试不稳定体验。
虽然所有工程师都会编写测试,但这些测试通常要等到完全失效后才会被更新,而且许多测试缺乏明确的责任归属。这些问题相互交织,导致开发人员很难判断测试失败的真正原因,需要反复尝试才能解决不稳定测试,最终给开发体验带来极大挫败感。
与此同时,内部基础设施也难以处理如此多的作业,导致 2019 年和 2020 年期间内部服务出现连锁故障。团队后来也针对内部服务连锁故障和成本增长问题进行了专门治理。
在拉取请求中,工程师需要等待很长时间才能获得测试结果。最糟糕的时候,每次提交的测试结果等待时间长达 95 分钟。这意味着,开发人员每次推送提交后,都必须等待很久,才知道测试是否通过。
在这个项目之前,Web 应用的每个拉取请求平均会执行超过 40 个端到端测试套件,p95 则超过 60 个测试套件。
2020 年初,团队的重点是让端到端测试可靠执行。许多端到端测试套件的单次执行失败率已经低于 1%。然而,当团队从更宏观的指标和开发者调研出发重新审视问题时,发现工程师仍然频繁遭遇测试不稳定、反馈循环缓慢和调试复杂等问题。
在评估开发者体验时,团队得出了一个重要结论:即使单个测试套件在合并前流程中的失败率很低,例如理想情况下为 1% 或更低,但当端到端测试数量足够多时,整体体验仍然会很糟糕。大多数拉取请求需要运行超过 60 个端到端测试套件。即使每个套件有 99% 的概率不失败,60 个套件叠加后,也意味着约 55% 的拉取请求至少会遇到一个失败测试套件。
工作流变更:从合并前测试转向合并后多层测试
考虑到测试覆盖率的增长速度,将所有测试套件都放在合并前流程中,已经不可持续。
从组织角度看,对所有失败测试套件进行分诊并持续维护,使它们始终符合标准,也并不现实。此外,在合并前运行所有测试,会给基础设施带来巨大负载,导致系统不稳定,因为并非所有下游服务和依赖项都能保证始终正常运行。
另一方面,如果大幅减少合并前测试数量,确实会显著缩短开发人员合并拉取请求所需时间,提高开发速度,但也会大幅增加缺陷进入生产环境的风险。
因此,团队需要找到一个平衡点:既保证代码安全,又兼顾开发速度。
在许多持续集成工作流中,合并前的端到端测试必须全部通过,拉取请求才能合并。在这个项目中,团队对工作流进行了调整,在合并后创建了两个额外的流水线。
新的测试流程分为三层:
- 合并前流程:这是原有流程。在开发过程中,只有不到 1% 的端到端测试会执行,并且必须全部通过,用户的拉取请求才能合并到主线。这些测试覆盖会阻塞合并和部署的高关键性功能。
- 合并后流水线:这是新增流程。代码合并到主线后,会针对每个提交执行更大比例的端到端测试,比例低于 10%。这些测试会在部署前向持续交付流水线提供信号。它们覆盖中等重要性的功能,会阻塞部署。
- 回归测试流水线:这是新增流程。代码合并到主线后,剩余端到端测试会针对批量提交执行。这些测试用于在每次部署中发现低优先级功能缺陷,并以每两小时一次的频率运行。它们采用批量执行方式,以减少测试本身或测试运行框架不稳定造成的误报。
过去,合并前测试会直接限制合并操作。现在,如果测试执行失败,用户会收到告警。当测试不稳定时,他们的工作流也会被阻塞。新的流水线还允许团队为不同类型的测试明确定义升级路径和负责人。
开发人员现在能够以更高的反馈频率开发和测试代码。同时,由于关键故障能够更准确归因,修复速度也更快。
不过,由于之前许多高关键性功能测试都在合并前执行,团队也需要调整分诊流程。目标是完善流程,尽可能减少有问题的代码通过持续交付流程并最终到达客户手中。

分诊流程变更:明确测试归属与故障优先级
为了让测试工程师和产品工程师对持续集成中的复杂故障形成共识,团队创建了一个自学课程和配套文档,用于解释新的告警机制以及它与内部沟通工具的集成方式。
完成课程后,工程师还会跟随其他工程师学习,从而获得更多关于如何识别流水线中各类故障、如何确定优先级的经验。
已识别问题的优先级会根据响应时间逐步提升,覆盖从回归测试、合并前测试、合并后测试到持续交付测试的不同阶段。
团队还创建了一个专门的告警频道,用于更好地了解持续集成系统中分散的问题。当合并后测试出现故障时,负责分诊的工程师会通过机器人自动收到告警。
各团队工程师确定了高优先级测试,并将它们移至合并后流程。这些测试旨在降低测试不稳定率,目标是不稳定率低于 0.1%,同时为重要用户体验提供高信号。
团队还改进了测试归属工具,并将每个测试分配到与其所属业务领域相关的特定频道。例如,消息相关测试会映射到消息团队的测试反馈频道,该团队成员会轮流负责处理该频道中的测试反馈。
这些努力通过明确预期,让组织内部逐步形成一致认识。不同工程部门共同参与,决定哪些测试对于维护高质量、高性能的持续交付流水线至关重要。
以人为本的告警设计:让合并后故障快速升级
接下来,我们深入介绍团队如何快速有效地升级合并后失败,并逐步将问题交给不同团队处理。
首先,团队创建了一个机制:当系统检测到某个测试连续失败两次或更多次时,就会在内部频道中发出告警。
这种“状态”基于有限状态机,可以理解为:当某个测试套件连续两次失败时,系统会将其映射到失败状态。团队使用内部分析工具和可视化告警能力,将这个状态展示出来。
能够访问这种状态之后,团队就可以精确定位测试套件开始失败的具体提交,从而确定导致失败的错误拉取请求。
当失败状态连续出现两次时,系统会向对应频道发送告警消息。
随后,团队发现还需要一个更清晰的问题处理流程。
此前,部署时的问题升级流程完全依赖人工操作。这意味着问题解决时间更长。这里的问题解决时间,是指合并后故障状态从出现到恢复所经历的时间。解决时间越长,缺陷发布给客户的可能性就越高。
当持续集成系统检测到连续的合并后故障时,团队会安排几类联系人通过单一渠道处理问题:
- 合并后测试联络人;
- 部署负责人;
- 相关拉取请求的开发者;
- 自动化故障排查工程师;
- 测试套件负责人。
过去,回复可能分散在多个渠道中,没有人能确定哪个渠道才是主线。例如,测试套件负责人频道、平台负责人频道、内部工具团队频道、部署频道等都可能出现讨论。
现在,系统会邀请相关工程师加入一个统一频道,然后再由他们添加其他可能需要参与的人员。
为此,团队修改了现有机器人,使其能够根据特定的合并后故障创建专属频道。机器人会搜索告警频道,然后向工程师发送故障分诊安排通知。分诊工程师可以点击升级按钮,系统会创建一个全新频道,并将相应联系人自动添加进去。机器人也会显示相关开发人员姓名,方便工程师在需要进一步升级时确认对象。
按照这个流程,测试故障分诊工程师会首先收到故障通知。该工程师会调查故障,确认故障是基础设施问题,还是测试本身不稳定导致的。随后,他会将问题上报给测试套件负责人,因为测试套件负责人通常对测试用例本身有更深入了解。
如果双方都认为当前问题并非由测试不稳定、服务级变更或基础设施级变更引起,就会邀请相关拉取请求的开发者加入讨论,并从那里开始调试。
最后,如果团队需要移除有问题的拉取请求,就需要调用部署命令,阻止该变更推送给客户。
这个看似冗长的升级流程,正是自动化发挥作用的地方。有问题的构建版本被忽略得越久,回滚错误提交或向前修复的成本就越高。这些成本包括工程时间,也包括潜在客户影响。
引入合并后故障升级流程后,团队可以更轻松地记录合并后故障的解决时间和分类时间,并精准定位频繁失败的测试套件,从而引起相关负责人关注。
这一流程非常重要,因为故障可能代表真实客户问题,需要测试工程师和产品工程师从不同视角进行故障诊断。
团队希望为用户创建一条可操作的升级路径,在最大限度减少干扰的同时,过滤掉误报。
由于连续失败并不一定总是有效故障,团队会先请测试负责人验证失败是否真实。例如,如果持续集成基础设施正在受到某个事件影响,导致合并后测试失败,平台工程师会快速查看失败日志,确认失败并不是即将交付给客户的新代码缺陷引起的。
在事件发生期间,团队会暂停所有新代码部署,直到持续集成基础设施恢复正常。
测试负责人是调试失败测试的第一道防线。由于团队为自动化测试设置了优先级排序机制,并在新工程师入职培训中解释了合并后测试升级流程,因此能够有效地将告警直接发送给负责优先级判断的工程师。
此外,优先级判断始终由两名工程师共同负责,这有助于快速诊断失败测试,并减少误判。
在实际落地中,这类告警分诊和故障升级流程往往涉及任务分派、项目协同、文档记录、即时沟通、排期跟进、工时投入和审批流转。团队可以借助 Worktile 这类通用项目协作系统统一管理任务、项目、文档、IM、目标、日历、甘特图、工时和审批流程,让合并后故障处理和跨团队协作更加清晰可控。
结论:用分层测试提升 CI/CD 安全性与开发效率
在过去一年多时间里,工程师们一直使用这种分层测试工作流,并在 Web 应用测试和部署方面获得了更快、更可靠的体验。
这一改变在不牺牲客户质量的前提下,提高了开发速度和开发者满意度。通过分层测试流程和前面提到的社会技术工作流,团队能够识别有问题的代码,并迅速将相关信息提供给相关团队,以便在代码交付给客户之前完成修复。
通过改进反馈循环,团队能够将许多测试转移到合并后执行,从而显著改善测试用户体验。
这个分层测试工作流项目,也帮助团队更好理解不同工程部门过去各自为政的运作方式,以及如何在战略和执行层面更好协同。
在过去六个月中,团队组建了一个跨部门工作组,由来自 12 个团队的高级工程师组成。这个工作组制定了一份北极星文档,概述测试和开发的目标、业务现状和战略重点。
每个目标都代表一个飞轮的一部分,通过增量项目逐步推进。目前,团队正在积极迭代一份共享路线图,用于打造卓越的持续集成体验。
这份路线图覆盖多个投资方向,例如提升可观测性,包括识别持续集成工作流中的瓶颈;减少端到端测试依赖;以及构建用于理解不同测试平台之间被测代码关系的模型和工具。
最终,这一项目证明:CI/CD 的安全性和速度并不是简单对立关系。通过更合理的测试分层、更清晰的告警机制、更明确的责任归属和更高效的分诊流程,团队可以在保护客户体验的同时,让开发人员更快、更稳定地交付高质量代码。
文章包含AI辅助创作:CI/CD 测试分层实践:如何平衡代码安全与开发速度,发布者:shang,转载请注明出处:https://worktile.com/kb/p/3978902
微信扫一扫
支付宝扫一扫