金字塔还是螃蟹?找到合适的测试策略

了解如何将不同的测试类型组合为适合您项目的合理策略。

欢迎回来!最后一篇文章针对如何处理不同的测试类型及其包含的内容提供了大量基础建议,并阐明了测试类型的定义。还记得这张小表情包吗?您或许想知道,您学到的所有测试类型如何协同工作。

一个带两个抽屉的橱柜,可以同时打开。

接下来,您将详细了解这一点。本文介绍了如何将这些测试类型组合为合理的策略,并选择与您的项目相符的一类策略。

您可以将这些策略与许多形状进行比较,以更好地了解它们的含义。下面列出了各个策略以及相应的规模和开发范围。

应用大小 团队构成 依赖手动测试 测试策略
仅限开发者 测试冰锥
测试螃蟹
开发者和质量检查工程师 测试冰锥
测试螃蟹
仅限开发者 测试金字塔
仅限开发者 测试奖杯
测试钻石
开发者和质量检查工程师 测试奖杯
测试螃蟹
仅限开发者 测试奖杯
测试蜂巢

下面我们来详细了解一下策略以及名称背后的含义。

确定测试目标:您希望通过这些测试实现什么目标?

在开始构建有效的策略之前,请先确定您的测试目标。您认为您的应用在何时进行了充分测试?

实现高测试覆盖率往往被视为开发者测试的最终目标。但这始终是最好的方法吗?在确定测试策略时,您可能需要考虑另一个关键因素 - 满足用户的需求。

作为开发者,您还会使用许多其他应用和设备。在这方面,您是依赖所有这些系统“正常工作”的用户。反过来,您需要依赖无数开发者尽力确保他们的应用和设备正常运行。为了扭转这种局面,作为开发者,您也要努力遵守这种信任。因此,您的首要目标始终应当是发布可正常工作的软件并为用户提供服务。这也会扩展到您编写的测试,以确保应用质量。肯特·C. Dodds 在其针对前端应用的静态、单元与集成与端到端测试这篇博文中进行了很好的总结:

您的测试与您软件的使用方式越相似,为您提供的信心就越高。

作者:Kent C. Dodds

Kent 将其描述为在测试时更有信心。您选择适合的测试类型越靠近用户,就越容易相信测试能够获得有效结果。换言之,爬得越高,您对金字塔的信心就越高。等一下,金字塔是什么?

确定测试策略:如何选择测试策略

首先,请确定您需要检查哪些部分,以确保满足这些要求。了解应使用哪些测试类型,以及在达到何种详细程度时可以最有把握地实现这一目标,同时保持高效的成本结构。许多开发者使用类比来解决这个问题。下面是最常见的几种类型,从大家熟知的经典入手。

许多形状,如金字塔、钻石、冰锥、蜂巢和奖杯;代表测试策略。

经典:测试金字塔

开始寻找测试策略后,您很可能会接触到测试自动化金字塔作为第一个类比。Mike Cohn 在他的《Succeeding with Agile》一书中介绍了这一概念。后来,Martin Fowler 在其实际测试金字塔一文中对这一概念进行了扩展。您可以用以下形式直观地表示金字塔:

测试金字塔。

如图所示,测试金字塔由三层组成:

  1. Unit。这些测试位于金字塔的基础层,因为它们执行速度快且易于维护。它们是独立的,并且针对的是最小的测试单元。例如,您可以参阅针对小型产品的典型单元测试

  2. 集成。这些测试位于金字塔中间,因为它们的执行速度可以接受,但与单元测试相比,这种测试能够让您更贴近用户。API 测试就是一种集成测试。您还可以将组件测试归类为此类型。

  3. E2E 测试(也称为界面测试)。这些测试会模拟真实用户及其互动。此类测试需要更多时间来执行,因此成本也更高。它们在金字塔的顶端。

信心与资源

如前所述,各层的顺序不重合。它们会显示优先级和相应的费用。这样您就可以清楚地了解应为每一层编写多少测试。您已在测试类型的定义中看到了这一点。

由于 E2E 测试最接近您的用户,因此,这种方式可以为您提供最高的信心,确保您的应用按预期运行。不过,它们需要完整的应用堆栈和模拟用户,因此可能也是最昂贵的。因此,您的信心会直接占用您执行测试所需的资源。

带有箭头的测试金字塔表示不同测试类型所需的置信度和资源方向。

为了解决这个问题,金字塔会让您更多地关注单元测试,并严格确定端到端测试涵盖的用例的优先级。例如,最重要的用户转化历程或最容易出现缺陷的位置。正如马丁·福勒所强调的那样,科恩金字塔中最重要的两个要点如下:

  1. 以不同的粒度编写测试。
  2. 获得的测试级别越高,需要进行的测试就越少。

金字塔进化了!测试金字塔的调整

多年来,人们一直围绕金字塔展开讨论。金字塔似乎过于简化测试策略,遗漏了很多测试类型,不再适合所有实际项目。因此,它可能具有误导性。金字塔失形了吗? Guillermo Rauch 对此有自己的观点:

编写测试。别太多。主要是集成。

作者:Guillermo Rauch

这是关于该主题的最常见引用之一,我们来详细了解一下:

  • “编写测试”。这不仅有助于建立信任,还有助于节省维护时间。
  • “不过分太多”。100% 覆盖率并不总是很好,因为这样您的测试就没有优先考虑,需要进行大量维护。
  • “以集成为主”。这里再次的重点是集成测试:它们在保持合理的执行时间的同时,为您提供每日的高置信度,因此具有最大商业价值。

这就需要您重新思考测试金字塔,并将关注重点转移到集成测试上。过去几年间,人们提出了很多调整方案,下面我们了解一下最常见的调整方案。

测试菱形

第一个调整消除了对单元测试的过度强调,如测试金字塔所示。假设您已经达到了 100% 的单元测试覆盖率。但是,下次重构时,您必须更新其中的许多单元测试,并且您可能想要跳过它们。所以它们会下降。

因此,随着集成测试的关注度更高,可能会出现以下形状:

测试菱形。

金字塔演变为钻石。您可以看到前面的三个图层,但它们的大小不同,并且单元图层已被剪切:

  • Unit。按照您之前定义的方式编写单元测试。但由于它们往往会削弱、优先处理和覆盖最关键的情况。
  • 集成。您了解的集成测试,用于测试单个单元的组合。
  • E2E。此层处理界面测试的方式与测试金字塔类似。注意只为最关键的测试用例编写端到端测试。

测试蜂巢

Spotify 引入了另一个调整版本,该调整与测试菱形类似,但进一步专用于基于微服务的软件系统。蜂窝测试是另一种直观的类比,用于模拟为基于微服务的软件系统编写的测试的粒度、范围和测试数量。由于微服务较小,微服务中最相当的复杂性并不在于服务本身,而在于它与其他服务的交互方式。因此,微服务的测试策略应主要侧重于集成测试。

测试蜂巢。

这个形状让人想起蜂巢的名字,也就是它的名字。它包含以下图层:

  • 集成测试。Spotify 的这篇文章使用了来自 J. B. Rainsberger 定义了这一层:“一项将通过或失败的测试,具体取决于另一个系统的正确性。”此类测试具有您需要考虑的外部依赖项,相反,您的系统可能是破坏其他系统的依赖项。与其他类比中的 E2E 测试类似,这些测试应仅用于最基本的情况,请谨慎使用。
  • 集成测试。与其他适配类似,您应该专注于这一层。它包含一些测试,这些测试以更隔离的方式验证服务是否正确,但仍与其他服务相结合。这意味着,测试还将包括一些其他系统,并侧重于互动点(例如通过 API 测试)。
  • 测试实现细节。这些测试类似于单元测试,后者侧重于代码的自然隔离部分,因此有其自身的内部复杂性。

如果您想详细了解此测试策略,请参阅 Martin Fowler 所写的这篇帖子将测试金字塔与蜂巢技术进行比较,以及 Spotify 的原创文章

测试奖杯

您已经看到反复关注集成测试。不过,您在上一篇文章中遇到的另一种类型不是测试,但它仍然是您在测试策略中应考虑的一个重要方面。测试金字塔和您目前看到的大多数调整都缺少静态分析。测试奖杯调整方式会考虑静态分析,同时继续专注于集成测试。测试奖杯来自 Guillermo Rauch 的一句话,由 Kent C. Dodd:

测试奖杯。

测试奖杯是用一种略有不同的方式描述测试粒度的类比。它有四个层:

  • 静态分析。它在这个类比中起到了至关重要的作用,它让您只需执行前面所述的调试步骤,即可捕捉错别字、样式错误和其他 bug。
  • 单元测试。它们可确保最小的单元得到适当的测试,但测试奖杯对它们的强调程度与测试金字塔不同。
  • 集成。与其他调整一样,这是主要关注点,因为它可以最佳方式平衡成本和更高的置信度。
  • 界面测试:包括端到端 (E2E) 和视觉测试,它们位于测试奖杯的顶部,类似于他们在测试金字塔中的作用。

要详细了解测试奖杯,请参阅 Kent C. 不要再说这个主题。

一些更侧重于界面的方法

这些都没什么问题,但无论你如何称之为“金字塔”、“蜂窝状”或“钻石”,无论你怎么称之为策略,都缺少一些东西。虽然测试自动化很有价值,但请务必注意,手动测试仍然非常重要。自动化测试应该可以减轻日常任务的负担,并使质量保证工程师腾出时间专注于关键领域。自动化测试不应取代手动测试,而应作为对测试的补充。是否有办法将手动测试与自动化功能集成在一起,以取得最佳效果?

测试冰锥和螃蟹

实际上,测试金字塔有两种调整版本,更侧重于这些以界面为中心的测试方式。两者都具有高置信度的优势,但由于测试执行速度较慢,因此代价自然也会增加。

第一个是测试冰锥,看起来像是相反的金字塔。没有手动测试步骤,也称为“测试披萨”。

测试冰锥。

冰锥更侧重于手动测试或界面测试,最少侧重于单元测试。在开发者刚开始开发测试策略时,我们往往会基于一些想法做出相应调整。ice Code 被认为是一种反模式,这是理所当然的。它在资源和手动工作方面成本很高。

测试蟹与测试冰锥类似,但更侧重于 E2E 和视觉测试:

那是测试蟹。

该测试策略还有另外一个方面:它会验证您的应用能否正常运行且看起来良好。测试螃蟹强调了目视测试的重要性,如上一篇文章中所定义。集成测试分为组件测试和 API 测试,更深入了后台,而单元测试在此处发挥的作用更加次要。您可以参阅这篇关于测试蟹的文章,详细了解此测试策略。

虽然这两种测试策略的成本较高,但也有其各自的适用:例如,适合需要较少测试或降低复杂性的小型项目。在这种情况下,专注于集成测试的全面测试策略可能过于工程化。

虽然这两种测试策略的成本更高,但它们也有其各自的适用,例如,在需要较少测试且无需涵盖大量复杂性的小型项目中也具有各自适用的范围。在这种情况下,专注于集成测试的全面测试策略可能过于复杂。

实用建议:制定策略!

至此,您已经了解了最常见的测试策略。我们从经典金字塔开始着手,逐渐了解了它的许多改编版本。现在,您需要针对自己的产品评估这些模型,并确定哪些模型最适合您的项目。这个问题的答案应该从大家都爱看的“视情况看”开始。但这并没有降低其准确性。

这需要视情况而定。

从上述(甚至遗漏)中选择最合适的测试策略取决于您的应用。它应该确定您的架构、要求,以及最重要的,也就是您的用户及其要求。所有这些信息可能因应用而异。这完全正常。请注意,您最重要的目标是为用户提供服务,而不是教科书上的定义。

在很多情况下,实际测试很难单独进行分离和定义。即使是 Martin Fowler 自己也强调了不同定义的积极方面,例如在单元测试方面。正如 Justin Searls他的推文中正确表述的那样:

[...] 编写表达性测试,以便确立明确的边界,快速、可靠地运行,并且仅在有实用价值的情况下才会失败。

作者:Justin Searls

将重点放在能够报告用户实际可能会遇到的错误且不会分散您对目标的注意力的测试上。测试的设计应使用户受益,而不是仅提供 100% 的覆盖率,或者讨论应编写哪种测试类型。

重点测试能够报告用户可能会遇到的真实错误,并且不会偏离您的目标。测试的设计应使用户受益,而不是仅仅 100% 地提供测试,或者引发有关您应编写特定测试类型的百分比的争论。