测试自动化真正困难的部分,不是启动工具,而是在不影响发布的前提下,让测试集稳定运行并逐步承担回归任务。
大多数自动化计划以同一种方式失败:团队决定开始,选定框架,设下完成期限,并计划在某个日期一次性切换。四个月后,框架配置时间是预期的 3 倍;测试集很脆弱,开发者每次改页面它都会失败;管理层逐渐失去耐心。
这首先是节奏与顺序问题,而不是工具问题。Testlio 汇总的研究显示,只有 5% 的公司实现完全自动化测试;不是自动化不起作用,而是大爆炸式转型还没产生结果就已崩溃。
有效的方法是两套系统并行运行。新的自动化测试持续加入,手工测试继续执行;自动化只有证明值得信任后,才接管特定流程。没有大爆炸式切换,没有期限压力,建设期间也不影响发布。
这一周不要写任何自动化测试。
对完整手工测试集应用三筛选条件框架,产出一份按优先级排序、恰好包含 10 个用例的清单。然后选择工具。本周只做基础设施:安装框架、配置环境并接入 CI,使空测试运行能够由 Pull Request 触发。
跳过这一步、马上开始写测试的团队,前两周通常都在排查一次失败到底是真实缺陷还是配置问题。这种不确定性成本高、很打击人,也是人们悄悄放弃计划的第一个原因。
第 1 周交付物:按优先级排序的 10 个测试用例清单;已安装工具;CI 已连接,且能成功触发空测试运行。
从清单里挑最简单的三个测试,而不是最重要的三个。目标是在写任何复杂测试之前,让 3 个测试能在 CI 中可靠运行。
简单测试能及早暴露基础设施问题。在第 3 个测试时发现选择器策略有问题或环境配置错误,修复成本很低;在第 37 个测试时才发现,就意味着已经在同一错误基础上再建了 34 个测试,成本高且令人沮丧。
本周第一天就把这些测试接入 CI,不要把它当作以后再补的基础设施。只有在人手动触发时才运行的测试,不是自动化测试,而是脚本执行的手工测试。CI 集成才使自动化真正成立。
继续按原样运行全部手工测试,此时尚未替代任何内容。
第 2 周交付物:每个 Pull Request 都会在 CI 中运行 3 个自动化测试。
多数团队会直接跳过这一周,但它决定计划会成功,还是会在 6 个月后悄无声息地死亡。
这周每天运行这 3 个测试,修复所有间歇性失败。严格审查测试代码:选择器是否绑定了开发者下个迭代可能改名或重构的实现细节?测试是否依赖时序,例如在慢速 CI Runner 上会出问题的 sleep(2000)?现在就消除脆弱性,而不是等到基于同一脆弱模式写完 40 个测试之后。
一套完全可信的测试集,即使只有 3 个测试,也胜过 50 个无法判断是真实缺陷还是基础设施噪音的测试。当测试集不值得信任时,人们就不会再处理它的失败。即使没人明说,计划也在那一刻结束了。
第 3 周交付物:3 个测试在 CI 中连续 5 天没有任何不稳定失败。
现在可以扩展,因为基础设施已经可靠,模式也经过验证。第 4 周增加第 4 至第 7 个测试;第 5 周完成第 8 至第 10 个测试。对每个新测试都使用第 3 周的标准:它没有稳定通过前,不进入下一个测试。不要急于加速,这种方法的全部价值就在于每个测试都要先赢得信任,才会继续写下一个。
第 5 周交付物:每次代码变更时,10 个自动化测试都能在 CI 中稳定通过。
对于已经被稳定自动化测试覆盖的流程,不再在每次发布前运行对应的手工回归版本。保留手工用例文档,用于探索式测试和重大功能变更;但对于日常回归,这些流程现在由自动化负责。
这才是切换:不戏剧化,不一次性完成,也不以牺牲任何一次发布为代价。
接着重复这个节奏:再用 6 周做另外 10 个测试,之后继续每 6 周循环。PractiTest 的 2025 年测试现状报告显示,26% 的团队已经用自动化替代约一半的手工测试工作,20% 的团队替代了 75% 或更多。增量推进的团队,才是最可能真正达到这一状态的团队。
只有在人手动触发时运行的测试不是自动化测试。自动化的全部价值存在于流水线中:在每次代码变更时捕获回归,而不是发布前一晚才发现问题。
请在第 2 周的第一天将首批测试接入 CI。对大多数团队,以下运行结构有效:
| 触发条件 | 运行内容 | 目标时长 |
|---|---|---|
| 每个 Pull Request | 冒烟测试:应用启动、登录、核心流程 | 5 分钟以内 |
| 每次合并到 main | 完整回归测试集 | 30 分钟以内 |
| 每晚 | 扩展测试集:性能、跨设备、边界场景 | 无严格限制 |
| 发布前 | 在真实设备矩阵上运行完整测试集 | 发布窗口开启前完成 |
关键原则是:冒烟测试为 Pull Request 设置门禁,快速、廉价且始终执行;完整回归测试集在合并到 main 时运行,更全面、更慢,触发频率也更低。
理解失败模式与理解成功模式同样有价值。多数计划会以五种方式之一失败;只要及早识别,大多数都可以避免。
表现:团队设定期限,例如到第三季度实现完全自动化。期限压力导致走捷径:测试脆弱、跳过稳定化、CI 集成不足。测试集不断失败,没有人信任它,团队悄悄回到手工测试。
修复方法:采用上述增量并行法。不要设置完成期限,也不要设置切换开关;只需持续积累逐个赢得信任的测试。
表现:测试使用 XPath 选择器、脆弱的资源 ID 或元素位置。开发者每个迭代重构页面时,测试就会失败,维护负担超过价值,测试集最终被放弃。
修复方法:这是设计问题,不是工具问题。使用语义化且稳定的选择器,例如无障碍标签、data-testid 属性和可见文本。采用页面对象模型(Page Object Model)集中管理 UI 引用,这样按钮移动时,只需更新 1 个文件而非 40 个测试。也可以使用依据上下文理解识别元素、而非依赖实现属性的 AI 工具。
表现:测试连续 3 个月都能通过,之后开发者上线重新设计却不更新测试。测试集变红后一直没有恢复;没人负责修复,最后被禁用。
修复方法:在编写第一个测试前就明确维护责任。把测试更新视为一等工程工作,并为每个迭代安排预算。一条实用规则是:每个改变功能的 Pull Request,都应更新覆盖该功能的自动化测试。失败的测试应阻止合并,而不是被忽略。
表现:管理层问我们有多少个测试,团队于是优化测试数量。他们写了 500 个测试,其中多数只测琐碎内容或彼此重复;测试集需要一小时才能运行完,也没有人看结果。
修复方法:衡量在缺陷流向用户前捕获到的回归。这才是能证明投资价值的指标。跟踪自动化测试最先发现了多少生产缺陷,以及这个数字每月如何变化。一个拥有 20 个可靠测试、能捕获真实回归的团队,比拥有 500 个没人信任的测试的团队处境更好。
表现:自动化在独立仓库中,由独立团队负责,也没有人通过开发流程审查。测试逐渐不再反映应用真实状态,持续漂移、失败,最终被禁用。
修复方法:自动化应与应用代码放在一起,在同一批 Pull Request 中审查,并被当作共享的质量基础设施。编写功能的团队,也要对覆盖该功能的测试负责。
许多团队在测试自动化上衡量了错误的东西。以下是值得跟踪和不值得优化的指标。
上线前捕获的回归:在某一时期内,自动化测试集发现并阻止流向用户的缺陷数量。这是主要指标,直接回答这项投资是否值得。
不稳定率:同一份代码下,测试运行产生不一致结果的比例,例如有时通过、有时失败。不稳定率高于 5%,意味着测试集正在制造噪音,侵蚀团队信任。应主动跟踪并积极修复。
从代码变更到获得测试结果的时间:如果 CI 流水线需要 45 分钟才返回结果,开发者在看到失败前可能已经切换了两次工作上下文。目标应是冒烟测试 5 分钟内出结果,完整测试集 30 分钟内出结果。
关键路径的测试覆盖:不是代码行覆盖率,而是最具业务关键性的 5 条用户流程是否已有自动化测试覆盖。跟踪具体哪些流程已覆盖、哪些未覆盖。
修复失败测试的平均时间:从测试变红到修复完成要多久?时间过长说明责任归属存在问题,或维护投入不足。
测试总数:脱离上下文毫无意义。500 个不稳定测试比 20 个可靠测试更糟。
代码覆盖率百分比:可作为单元测试的粗略启发指标,但很容易被人为刷高,也无法反映实际测试质量。
自动化百分比:我们已自动化 60% 的测试用例,无法说明具体覆盖了哪些流程、它们有多可靠,或剩下的 40% 是否重要。
收录于 FunTester 原创专题:软件测试的道与术
相关阅读:自动化流程管理:从混乱到有序的实践 · 5 步法助力自动化转型 · 自动化测试转型挑战及其解决方案 · 持续测试、持续集成、持续交付、持续部署和 DevOps · 如何维护自动化测试