译者 | 陈峻
审校 | 孙淑娟
2009年,Mike Cohn在他的Succeeding with Agile 一书中用金字塔来比喻软件的测试模型。逐渐,该说法流传开来,如今它已成为了业界的行业标准。
总的说来,测试金字塔能够直观地表示出测试的标准化逻辑结构。它由如下三个不同的层次所组成:
金字塔的底部是单元测试。该单元实际上是一些小段的逻辑代码。它们可以是函数、类、甚至是类中的方法。单元测试仅会检查目标单元的行为,是否符合开发人员的预期。开发人员可以通过编写单元测试,在无需依赖任何其他组件、服务或UI的情况下,直接调用被测试代码,进而评估其输出。
金字塔的中间层是集成测试,Mike在他的书中也称为“服务测试”,其主要目的是测试系统的不同组件是如何协同工作的。例如,代码中的模型是否可以正确地与数据库交换数据,或者某个方法是否可以从API中检索到信息。同样,集成测试不需要UI的交互,便可以直接调用接口处的代码。
金字塔的顶层是端到端(end-to-end,E2E)测试,也称为UI测试,E2E是从最直观的角度进行测试,即通过运行应用程序,来查看其效果。当然,E2E测试并不一定需要人工去执行,而可以完全依靠自动化。E2E测试能够模拟出每个用户与应该交互的动作,例如:单击按钮、输入信息、以及捕获UI的显示内容等。
可见,这三种类型的测试会涉及到不同的范畴:
单元测试,只能在最基本的层面上发现逻辑错误。它们速度比较快,而且运行时所需的资源也比较少。
集成测试,主要验证应用服务和数据库,是否能与编写的代码和类进行良好的系统化协同。他们只能在两个或多个组件交互的接口处发现问题。
E2E测试,关注能否启动的完整应用程序。由于属于最全面的测试类型,因此它在运行时往往会耗费最多的计算资源和时间。
1.测试金字塔的复杂性
在了解了测试金字塔的基本测试层次后,让我们来讨论一下每种测试的复杂性。单元测试由于比较简单,因此易于编写和维护。虽然它们仅仅测试的是非常狭窄的代码部分,但是却经常被使用到。我们往往可以在几秒钟内运行数千个单元测试。
集成测试在复杂性、以及数量级上与单元测试差不多,毕竟我们只对待测应用程序的“边界”部分感兴趣。不过,与单元测试相比,集成测试需要更多的资源才能运行。
E2E测试则具有编写复杂、难以维护、需要大量资源、并且运行缓慢等特征。不过,由于我们可以通过各种E2E测试工具来覆盖更多的应用程序,因此我们需要执行的测试工作量并不大。
由金字塔的形状可知,每一层次的宽度会与该层的测试量成正比。也就是说,端到端的测试量相对较少、而集成测试的数量不及单元测试那么多、那么广。
如前所述,三类测试的复杂程度和代码库的覆盖率都是逐层增加的。下图展示了各种测试在编写、运行和维护方面的工作量比例。据此,您可以最大限度地利用更少的工作,找到更多的缺陷与错误。
2.如何给测试金字塔符能
在项目伊始时编写E2E测试往往极富挑战性。除非开发团队能够采用BDD等框架,并从一开始就着手编写验收测试(https://semaphoreci.com/blog/the-benefits-of-acceptance-testing),否则大多数E2E测试都将只能在基本原型、或最小可行产品就绪时,才能被编写。如下图所示,开发人员在整个开发过程中,也会逐步增加单元测试与集成测试的编写工作量。
让我们再来看看测试的效率。众所周知,缓慢的测试往往会拖慢生产环境所需的重要信息反馈。因此开发人员需要高效地运行三种测试套件,以稳定提升软件质量。
位于金字塔底部的单元测试具有最高的运行效率,因此开发人员往往乐于编写与使用。相反,鉴于复杂性,E2E测试的效率最低。一个大型的Web应用程序往往需要进行数千个单元测试、数百个集成测试、以及几十个E2E测试。而它们的用时,可以体现在下图中:
3.使用测试奖杯来测试前端
测试金字塔的历史可以追溯到2009年。随着技术的快速发展,人们在应对不同的开发需求时,也可能需要不同的测试模型。由Kent C. Dodds提出的测试奖杯(https://twitter.com/kentcdodds/status/960723172591992832)就是一种针对前端开发所构建的测试模型。
测试奖杯重排了优先级。它认为由于大多数现代UI都会依赖于各种后端组件,而且难以开展单独的测试,因此集成测试才是王道。
与金字塔相比,单元测试处于次要地位,而且可以被ESLint和JSHInt等静态测试工具所取代。它们通过扫描代码,便可发现诸如:使用了不安全的语句、或未遵守变量命名规则等潜在问题。
奖杯的顶端是E2E测试,它与在测试金字塔中的占比相似。
4.测试矩阵
在测试金字塔中,我们往往容易忽略测试结果可信度的问题。也就是说,唯一可以真正验证应用程序可行性的测试,只有E2E测试。通常,我们认为开发人员投入在测试上(如E2E测试)的精力越多,测试结果的可信度就越高。对此,Gleb Bahmutov和Roman Sandler提出了测试矩阵(https://portal.gitnation.org/contents/testing-pyramid-makes-little-sense-what-we-can-use-instead)作为规划测试相关策略时的工具。
如上图矩阵所示,开发人员精力的投入是从左到右增加的,而可信度是从下到上上升的。显然,最佳位置是在绿色区域。而大多数软件项目都是从低投入和低可信度的黄色区域开始的。
随着项目的成熟和新功能的添加,测试需求也会随之处于熵增的状态。倘若测试团队未能在测试方案上持续改进和维护,那么他们会很快滑到红色区域。
对此,我们应该如何以尽量少的投入,增加测试的可信度呢?我们需要定期重新评估如下五类与测试相关的方面:
安装:包括安装和设置测试框架所涉及的工作。
编写:涉及到为给定框架编写测试的复杂程度、以及开发人员的技能水平。
运行:包括运行测试套件的难度、以及CI/CD的性能。
调试:涉及到发生测试失败时,发现和修复问题难易程度。
维护:包含在项目的整个生命周期中,维护测试所耗费的精力。
在该模型中,我们往往需要在项目的开端,给予单元测试一定的投入。不过,一旦项目功能稳定下来,开发团队就需要通过添加更多的E2E测试、以及减少其他测试类别,来平衡组合测试。据此,测试有效性在稳步增加的同时,团队可以有条不紊地调整在不同类别上的投入。
5.谨防教条思维
由于速度、成本和维护问题,金字塔在一定程度上限制了我们尽早地开展E2E测试。当然,也有人认为:鉴于端到端测试更接近于用户的真实场景操作,团队可以通过应用提供的公共界面予以开展。因此,如果您更改了后台的实现,甚至更换了整个后端的话,那么E2E测试不应被推倒重来,而只需沿用原有的测试案例,进行测试微调便可。据此,其维护的工作量实际上也并非多得惊人。
当然,每个团队、每个项目、以及每个组织都是不同的。而且随着需求的变化,团队可能会需要通过重新决定或规范化测试套件,以灵活的方式停止现有的、或评估新的测试模型,按需进行调整,以达到多快好省的测试效果。
6.小结
历史悠久的测试金字塔模型,为整个测试领域树立了一个典型的通用模型,方便大家参考与交流。当然,随着新技术、新实践、以及新理念的出现,各种不同的改进模型也相继出现。它们各有专攻,服务于特定的开发领域。其中不乏服务于CI/CD管道的自动化测试套件。总之,您需要根据自己的实际项目,来选择最适合的测试套件。
原文标题:https://dzone.com/articles/the-testing-pyramid-how-to-structure-your-test-sui
译者介绍
陈峻 (Julian Chen),51CTO社区编辑,具有十多年的IT项目实施经验,善于对内外部资源与风险实施管控,专注传播网络与信息安全知识与经验;持续以博文、专题和译文等形式,分享前沿技术与新知;经常以线上、线下等方式,开展信息安全类培训与授课。