可测试性 vs. 可自动化性:为何大多数自动化工作在开始前就失败
Source: Dev.to
测试自动化很少因为团队选择了错误的工具而失败。
它往往更早就失败——通常在编写第一个测试之前——因为系统在设计时没有考虑如何进行测试或自动化。
当自动化变得不稳定、缓慢或不可靠时,默认的反应是可预测的:重写测试、切换框架、添加重试,或引入承诺更稳定的新工具。这些做法有时能暂时减轻痛苦,但很少能解决根本问题。随着时间推移,自动化变成了团队只能容忍而不信任的东西。
根本原因通常是对两个密切相关但本质上不同的概念——testability 和 automatability——的误解。
微妙的区别,改变一切
可测试性(Testability)和可自动化性(Automatability)在工程讨论中常被交替使用,但它们解决的是不同的问题。
- 可测试性 关注系统有多容易被理解和诊断。一个可测试的系统会清晰地暴露其状态。当出现故障时,系统帮助你了解发生了什么以及原因。日志有意义,信号明确,行为可以在无需猜测的情况下被观察到。
- 可自动化性 关注系统能被机器可靠地驱动的程度。它强调确定性、稳定性和可控性。一个可自动化的系统在自动化操作下表现一致,即使系统在演进也能保持这种一致性。
团队常犯的错误是认为良好的自动化自然意味着良好的可测试性。实际上,自动化依赖于可测试性。当可测试性薄弱时,自动化只能通过增加复杂度来弥补——而这种复杂度最终会因自身的重量而崩溃。
为什么自动化成为替罪羊
当自动化测试在没有明确解释的情况下失败时,自动化就成了显而易见的问题。流水线变红,发布信心下降,工程师失去对测试结果的信任。此时,自动化不再被视为安全网;它变成了噪音。
常常被忽视的是,这些失败是 症状,而非原因。测试超时、未能定位元素或产生不一致的结果,往往反映出系统本身更深层的不确定性。自动化只是比手动测试更早、更频繁地显现出这种不确定性。
人类在应对模糊性方面表现出惊人的能力。我们会刷新页面、重试操作、推断意图,然后继续前进。自动化没有这种直觉。它需要明确的信号、稳定的行为和可预测的状态转移。当这些缺失时,自动化就会挣扎,并因此被指责。
工具无法解决根本性问题
现代框架让自动化变得更易获取且更宽容。它们更好地处理等待,提供更丰富的诊断信息,并减少样板代码。但它们并不能——也无法——解决根本的设计问题。
没有任何工具能够弥补以下问题:
- 用户界面不断重新渲染且缺乏稳定标识符
- 业务逻辑埋在 UI 事件处理程序中
- 异步工作流没有可观察的完成信号
- 系统仅以视觉方式而非编程方式暴露结果
在这些情况下切换工具可能会暂时降低摩擦感,但并未改变根本的不确定性。最终,同样的问题会再次出现,只是以不同的 API 形式呈现。
自动化摩擦是信号,而非失败
团队能够做出的最重要的思维转变之一,就是把自动化难度视为系统的反馈,而不是测试的失败。
当测试编写困难、难以稳定或难以调试时,系统正在向你传递信息。它在告诉你行为是隐式的而非显式的,状态是隐藏的而不是可观察的,控制是分散的而不是有意的。
倾听这些反馈的团队不仅会改进他们的测试,还会提升架构、可诊断性和运营成熟度。忽视这些反馈的团队会积累自动化债务——最终甚至会放弃大量的测试套件。
为什么在自动化规模化之前这很重要
误解可测试性和可自动化性的代价会随规模的扩大而增长。项目初期,糟糕的设计选择可能只会让少量测试变慢。但随着时间推移,它们会演变成不稳定的流水线、冗长的排查周期以及脆弱的发布流程。
这正是自动化策略不能与系统设计分离的原因。自动化不是后期才出现的阶段,而是一种约束,应当从一开始就影响软件的构建方式。
弄清楚可测试性与可自动化性的区别,是将自动化打造为资产而非负担的第一步。
接下来会怎样
在下一篇文章中,我们将更深入探讨团队经常面临的一个问题:
如何判断一个失败的测试是自动化本身的问题,还是应用程序设计的问题?
正是这一区别决定了大多数自动化工作是稳定下来还是逐渐瓦解。
如果你想构建能够自信扩展而非充满摩擦的自动化,请关注本系列。