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

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

欢迎回来!上篇文章介绍了有关如何处理不同测试类型及其内容的大量基础知识,并阐明了测试类型定义。还记得这张小模因图片吗?您可能想知道您学到的所有测试类型如何协同工作。

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

接下来,您将学习如何做到这一点。本文简要介绍了如何将这些测试类型组合成合理的策略,并选择适合您的项目的策略。

您可以将这些策略与多种形状进行比较,以便更好地理解它们的含义。下面列出了各种策略及其各自的大小和开发范围。

应用大小 团队组成 依赖于手动测试 测试策略
仅限开发者 测试冰淇淋蛋卷
测试螃蟹
开发者和质量检查工程师 测试冰淇淋蛋卷
测试螃蟹
仅限开发者 测试金字塔
仅限开发者 测试奖杯
测试钻石
开发者和质量检查工程师 测试奖杯
测试螃蟹
仅限开发者 测试奖杯
测试 Honeycomb

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

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

在着手制定良好的策略之前,请先确定您的测试目标。您认为何时应用已完成充分测试?

在测试方面,开发者通常将实现较高的测试覆盖率视为最终目标。但这是否始终是最佳做法?在确定测试策略时,可能还需要考虑另一个关键因素:满足用户需求。

作为开发者,您还会使用许多其他应用和设备。从这个角度来看,您是依赖所有这些系统“正常运行”的用户。反过来,您也依赖无数开发者尽最大努力使其应用和设备正常运行。作为开发者,您也应努力践行这种信任。因此,您的首要目标始终应是交付可正常运行的软件并为用户提供服务。这也适用于您编写的用于确保应用质量的测试。Kent C. Dodds 在其前端应用的静态测试与单元测试、集成测试与端到端测试一文中对此进行了总结:

测试越能反映软件的使用方式,您对测试结果的可信度就越高。

作者:Kent C. Dodds

Kent 将其描述为对测试充满信心。选择合适的测试类型,越能贴近用户,您就越能相信测试结果的有效性。换句话说,您在金字塔中的位置越高,您就越有信心。但请等一下,什么是金字塔?

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

首先,确定您需要检查哪些部分的要求,以确保它们符合要求。了解应使用哪些测试类型,以及在哪种详细程度下可以获得最高的信心,同时保持高效的费用结构。许多开发者会通过类比来理解这个主题。下面列出了最常见的几种,首先是众所周知的经典广告。

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

经典:测试金字塔

刚开始寻找测试策略时,您可能会首先看到测试自动化金字塔。Mike Cohn 在其著作《Succeeding with Agile》中介绍了这一概念。后来,Martin Fowler 在其实用测试金字塔一文中对该概念进行了扩展。您可以直观地表示金字塔,如下所示:

测试金字塔。

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

  1. 单元。您会在金字塔的基础层找到这些测试,因为它们执行速度快且易于维护。它们是隔离的,并且定位到最小的测试单元。例如,请参阅一款非常小的产品的典型单元测试

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

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

置信度与资源

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

由于 E2E 测试最贴近用户,因此可以让您最大限度地确信应用能否按预期运行。不过,它们需要完整的应用堆栈和模拟用户,因此也可能是成本最高的。因此,置信度与执行测试所需的资源直接竞争。

测试金字塔,其中箭头显示了不同测试类型的置信度和所需资源的方向。

该金字塔图表旨在通过让您更加专注于单元测试并严格确定 E2E 测试涵盖的用例的优先级来解决此问题。例如,最重要的用户历程或最容易出现缺陷的地方。正如 Martin Fowler 所强调的那样,Cohn 金字塔中最重要的两个要点如下:

  1. 编写不同粒度的测试。
  2. 等级越高,测试次数就越少。

Pyramid 已升级!测试金字塔的调整

几年来,人们一直围绕金字塔展开讨论。该金字塔似乎过于简化了测试策略,忽略了许多测试类型,并且不再适用于所有实际项目。因此,可能会产生误导。金字塔是否变形了? Guillermo Rauch 对此有自己的看法:

编写测试。不多。主要是集成。

作者:Guillermo Rauch

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

  • “编写测试”。这不仅是因为它可以建立信任,还因为它可以节省维护时间。
  • “不多”。100% 的覆盖率并不总是好事,因为这样会导致测试没有优先级,并且需要进行大量维护。
  • “主要集成”。同样,我们重点关注集成测试:它们可在保持合理的执行时间的同时,每天为您提供高置信度,因此具有最高的业务价值。

这会让您重新思考测试金字塔,并将注意力转移到集成测试。过去几年,许多人提出了各种改进建议,下面我们来看看最常见的改进建议。

测试钻石

第一个调整是消除对单元测试的过度强调,如测试金字塔所示。假设您已实现 100% 的单元测试覆盖率。不过,下次重构时,您将不得不更新其中的许多单元测试,并且可能会想跳过它们。因此,它们会被侵蚀。

因此,结合对集成测试的更大关注,可能会出现以下情况:

测试钻石。

金字塔演变为钻石。您可以看到前三个图层,但尺寸不同,并且单元图层已被剪裁:

  • 单元。按照之前定义的方式编写单元测试。不过,由于这些功能的效果会逐渐降低,因此请优先考虑并仅涵盖最关键的用例。
  • 集成。您熟悉的集成测试,用于测试单个单元的组合。
  • E2E。此层处理的界面测试与测试金字塔类似。请务必仅为最重要的测试用例编写 E2E 测试。

测试蜂巢

Spotify 还引入了另一种改进,它与测试金刚钻相似,但更专门针对基于微服务的软件系统。测试蜂巢图是另一种直观的类比,用于表示为基于微服务的软件系统编写的测试的精细程度、范围和数量。由于微服务的体积较小,因此微服务中最复杂的部分不是服务本身,而是它与其他服务的交互方式。因此,微服务的测试策略应主要侧重于集成测试。

测试蜂巢。

这种形状让人联想到蜂巢,因此得名。它包含以下层:

  • 集成测试。Spotify 的文章引用了 J. B. Rainsberger 对此层进行了定义:“根据另一个系统的正确性而通过或失败的测试。”此类测试具有您需要考虑的外部依赖项,反之,您的系统也可能是破坏其他系统的依赖项。与其他类比中的 E2E 测试类似,请谨慎使用这些测试,仅针对最重要的用例使用。
  • 集成测试。与其他适应方式类似,您应重点关注此层。它包含的测试以更隔离的方式验证服务的正确性,但仍会与其他服务结合使用。这意味着,测试还将涵盖一些其他系统,并重点关注互动点(例如,通过 API 测试)。
  • 测试实现细节。这些测试类似于单元测试,即专注于自然隔离且具有自身内部复杂性的代码部分的测试。

如需详细了解此测试策略,请参阅 Martin Fowler 撰写的将测试金字塔与蜂巢图案进行比较的帖子,以及 Spotify 的原始文章

测试奖杯

您已经看到,我们反复强调集成测试的重要性。不过,您在上一篇文章中提到的另一种类型并非理论上的测试,但仍然是您在制定测试策略时应考虑的重要方面。测试金字塔和您目前看到的大多数改编版本都没有提及静态分析。我们还提供了测试奖杯自适应功能,可在关注集成测试的同时兼顾静态分析。测试奖杯源自 Guillermo Rauch 之前的引言,由 Kent C. Dodds:

测试奖杯。

测试奖杯是一种比喻,以略有不同的方式描绘测试的粒度。它有四层:

  • 静态分析。它在此类比中发挥着至关重要的作用,只需运行前面介绍的调试步骤,即可捕获拼写错误、样式错误和其他 bug。
  • 单元测试。它们可确保对最小的单元进行适当的测试,但测试奖杯不会像测试金字塔那样强调它们。
  • 集成。这也是主要关注点,因为它能以最佳方式平衡成本和更高的置信度,与其他自适应方法一样。
  • 界面测试。包括端到端测试和视觉测试在内的这些测试位于测试奖杯的顶部,这与它们在测试金字塔中的作用类似。

如需详细了解测试奖杯,请参阅 Kent C. Dodds 的文章。

一些更侧重于界面的方法

这一切都很好,但无论您将自己的策略称为“金字塔”“蜂窝”还是“钻石”,都还缺少一些东西。虽然测试自动化非常有用,但请务必注意,手动测试仍然必不可少。自动化测试应减轻日常任务,让质量保证工程师能够专注于关键领域。自动化测试应与手动测试相辅相成,而不是取代手动测试。有没有方法可以将手动测试与自动化测试集成,以获得最佳结果?

测试冰淇淋和测试螃蟹

测试金字塔确实有两种改编版本,它们更侧重于这些以界面为中心的测试方法。这两种方法都具有高置信度的优势,但由于测试执行速度较慢,因此成本自然更高。

第一个是测试冰淇淋,看起来像倒过来的金字塔。如果不进行手动测试步骤,它也称为“测试披萨”。

测试冰淇淋蛋筒。

冰淇淋对手动测试或界面测试的关注度较高,对单元测试的关注度较低。在开发者刚开始着手项目时,他们对测试策略的想法可能还很少,但随着项目的推进,测试策略也会逐渐成形。ice 代码被视为反模式,这是有道理的。它在资源和手动工作方面成本高昂。

测试螃蟹与测试冰淇淋相似,但更侧重于端到端测试和视觉测试:

测试螃蟹。

此测试策略还包含一个方面:验证应用的功能和外观是否良好。测试螃蟹强调了视觉测试的重要性,上文对此进行了介绍。集成测试(分为组件测试和 API 测试)会进一步转移到后台,而单元测试在此处的作用更为次要。如需详细了解此测试策略,请参阅这篇介绍测试螃蟹的文章

虽然这两种测试策略的成本较高,但在某些情况下还是有用武之地:例如,在需要较少测试或需要覆盖较少复杂性的较小项目中。在这种情况下,专注于集成测试的全面测试策略可能过于复杂。

虽然这两种测试策略的成本较高,但在某些情况下,它们还是有用武之地,例如,在需要较少测试且不需要涵盖大量复杂性的较小项目中。在这种情况下,专注于集成测试的全面测试策略可能不必要地复杂。

实用建议:制定策略!

您现在已经了解了最常见的测试策略。您从经典的测试金字塔入手,了解了其许多变体。现在,您需要针对您的产品评估这些选项,并确定哪个选项最适合您的项目。对这个问题的回答应该以人人喜闻的“取决于”开头。不过,这并不会降低准确性。

这需要视情况而定。

从上述(甚至未提及的)测试策略中选择最合适的测试策略取决于您的应用。它应符合您的架构、您的要求,以及最重要的是,您的用户及其要求。所有这些可能因应用而异。这是完全正常的。请记住,您最重要的目标是服务用户,而不是遵循教科书定义。

在大多数情况下,现实世界的测试很难单独分离和定义。就单元测试而言,就连 Martin Fowler 本人也强调了不同定义的积极方面。正如 Justin Searls他的推文中正确指出的那样:

[…] 编写能够明确界定边界、快速可靠地运行且仅因有用原因而失败的富有表现力的测试。

作者:Justin Searls

重点关注报告用户可能会遇到的实际错误的测试,不要偏离目标。测试应以便于用户为目标,而不仅仅是提供 100% 的覆盖率或争论要编写哪种测试类型的百分比。

专注于报告用户可能会遇到的真实错误的测试,不要偏离目标。测试应以利于用户为目标,而不仅仅是提供 100% 的覆盖率,也不应引发关于您应编写特定测试类型的百分比的争论。

Twitter