测试金字塔

2012年5月1日

测试金字塔是一种思考如何使用不同类型的自动化测试来创建平衡的测试组合的方式。其核心要点是,您应该拥有比通过 GUI 运行的高级 广域堆栈测试 更多的低级 单元测试

在我的职业生涯中,大部分时间测试自动化意味着通过应用程序的用户界面驱动应用程序的测试。此类工具通常会提供记录与应用程序交互的功能,然后允许您回放该交互,并检查应用程序是否返回相同的结果。这种方法最初效果很好。记录测试很容易,并且测试可以由不了解编程的人员进行记录。

但这种方法很快就会遇到麻烦,变成一个 冰淇淋锥。通过 UI 进行此类测试速度很慢,会增加构建时间。通常它需要安装测试自动化软件的许可证,这意味着它只能在特定机器上完成。通常这些无法轻松地在“无头”模式下运行,无法通过脚本监控以将其放入适当的部署管道中。

最重要的是,此类测试非常脆弱。对系统的增强很容易导致大量此类测试失败,然后必须重新记录这些测试。您可以通过放弃记录回放工具来减少此问题,但这会使测试更难编写。 [1] 即使在编写它们时采用良好的做法,端到端测试也更容易出现 非确定性问题,这会损害对它们的信任。简而言之,通过 UI 运行的端到端测试是:脆弱的、编写成本高昂的,并且运行时间长。因此,金字塔认为,您应该通过单元测试进行更多自动化测试,而不是通过传统的基于 GUI 的测试。 [2]

金字塔还主张使用一个中间层测试,这些测试通过应用程序的服务层运行,我称之为 皮下测试。这些测试可以提供许多端到端测试的优势,但避免了处理 UI 框架的许多复杂性。在 Web 应用程序中,这将对应于通过 API 层进行测试,而金字塔的顶部 UI 部分将对应于使用诸如 Selenium 或 Sahi 之类的工具进行测试。

测试金字塔在敏捷测试圈中经常出现,虽然其核心信息是合理的,但关于构建一个平衡的测试组合还有更多内容要讲。一个常见的问题是团队混淆了端到端测试、UI 测试和面向客户测试的概念。这些都是正交的特征。例如,一个丰富的 JavaScript UI 应该使用诸如 Jasmine 之类的工具,通过 JavaScript 单元测试测试其大部分 UI 行为。一组复杂的业务规则可以在面向客户的表单中捕获测试,但仅在相关模块上运行,就像单元测试一样。

我一直认为,高级测试是作为第二道测试防线存在的。如果您在高级测试中遇到失败,不仅您的功能代码中存在错误,而且还缺少或不正确的单元测试。因此,我建议在修复由高级测试暴露的错误之前,您应该使用单元测试复制该错误。然后,单元测试确保错误永远消失。

进一步阅读

Google 测试博客 扩展了为什么您不应该依赖端到端测试。

Adrian Sutton 解释了 LMAX 的经验,这表明 端到端测试可以发挥重要而有价值的作用

一些作者认为金字塔不是一个好的测试分布,更喜欢更多的集成测试和更少的单元测试。但由于 “单元测试”的不同定义,这种差异可能是虚幻的。

致谢

Kevin Dishman 给了我添加成本和速度箭头到插图的想法

词源

大多数人知道测试金字塔是因为 Mike Cohn,他在 2009 年的书 敏捷成功 中描述了它。在书中,他将其称为“测试自动化金字塔”,但在使用中通常简称为“测试金字塔”。他最初是在 2003-4 年与 Lisa Crispin 谈话时绘制的,并在 2004 年的一个 Scrum 聚会上进行了描述。Jason Huggins 在 2006 年左右 独立提出了同样的想法。

修订

2016 年 8 月 7 日:更改插图

2017 年 11 月 15 日:添加词源

注释

1: 记录回放工具几乎总是任何类型的自动化的糟糕主意,因为它们抵抗可变性并阻碍有用的抽象。它们只值得作为生成脚本片段的工具,然后您可以像传统的 Emacs 一样,将其编辑为适当的编程语言。

2: 金字塔基于这样的假设:与更集中的测试(如单元测试)相比,广域堆栈测试成本高、速度慢且脆弱。虽然这通常是正确的,但也有例外。如果我的高级测试速度快、可靠且易于修改,那么就不需要低级测试。