自动化测试的类型

为不同类型的测试指定的名称往往在各个代码库中都具有共同的主题,但它们没有特别严格的定义。本课程就每种测试的含义提供了一些准则,但其他资源可能会提供不同的定义。

在前面的页面中,我们介绍了单元测试组件测试的示例(在我们的示例中,我们指的是 React 组件)。我们可以将这两种方法放置在测试金字塔中较低位置(或其他形状!),因为它们复杂度较低且运行速度快,但实用性可能不及更复杂的集成测试

一些测试策略形状的示例:金字塔、切割的钻石、圆筒冰淇淋、六边形和奖杯。
测试策略形式各异。

常见测试类型

单元测试

单元测试的范围最小。它们往往用于以几乎数学方式测试小部分代码或纯无状态代码:如果我为您的代码提供输入 X、Y 和 Z,其输出应为 A、B 和 C。

包含单元测试的代码通常没有外部依赖项,例如从网络中提取或者隐式使用任何其他函数或库。它是代码的树节点,您可以“剪掉”并自行测试。

虽然单元测试的编写和运行速度往往很快,但测试小单元代码也有可能无法提供实用信息。通常,一个代码单元不与其他代码互动意味着您最好在更高的级别进行测试,以降低风险。

组件测试

对于 Web 开发者,“组件”这一名称会过载,通常意味着用户可见的组件,例如 React 组件或 Web 组件。它更宽泛的定义是一个可测试的工作块,例如具有外部依赖项的类。为进行有效的测试,必须模拟或跳过此组件的依赖项。

由于现代 Web 开发实践植根于组件的概念,因此组件测试是一种考虑测试的实用方式:例如,您可能会确定每个组件都需要测试。如果单个开发者或小型团队声明对某个组件拥有明确的所有权,那么对组件测试进行后续测试也很简单。但是,模拟复杂的依赖项可能很困难。

集成测试

此类测试往往会对一小部分代码组件、模块、子系统或其他有意义的部分一起测试,以确保它们能够正常运行。这个定义非常含糊。对于 Web 开发者,假设您要测试的代码并非网站的真实生产 build(甚至非常接近),但仍连接系统的各种相关组件。

这可能甚至包括“实际”依赖项,例如处于测试模式下的外部数据库,而不是纯模拟。例如,您的集成测试可以确认测试数据库中是否包含某些内容,而不是指出 query() 将始终返回相同的两个条目。数据本身不太重要,但您现在正在测试是否可以成功连接到数据库并成功查询数据库。

您可以编写具有广泛影响的相对简单集成测试,而且可以使用断言进行检查,因为连接到不同组件的单个操作可能会产生一系列可衡量的影响。因此,集成测试可以有效地证明您的复杂系统会按预期运行。但是,它们可能难以编写和维护,并且可能会引入不必要的复杂性。例如,如果为集成测试编写 FakeUserService,就会要求它和 RealUserService 都必须实现 UserService

冒烟测试

这些测试应该很快完成,并确定代码库是否处于合理的状态。在实践中,这主要意味着对代码执行简单的测试会对您的体验产生广泛影响。

例如,在已登录的大型 Web 应用中,这可以确保登录和身份验证系统正常运行,因为如果没有它,应用将无法使用,进一步测试也毫无关系。

在大型代码库中,冒烟测试非常适合在 package.json 的 test 脚本下运行。手动测试也可以作为冒烟测试的一种。

回归测试

回归测试是一种冒烟测试,在发布新版本或其他功能后,它可确保现有功能继续正常运行,或者旧 bug 不会重新引入。

这与测试驱动开发 (TDD) 的概念有关。为明确触发 bug 而后用于确保 bug 修复的测试用例将计为回归测试用例,因为其存在应该会防止同一 bug 返回。

不过,如果没有优秀的解决方案,回归测试可能是一个问题。这是一个经常被业务需求提及的术语:随着功能的开发,务必要确保旧功能的不中断。经过充分测试的代码库应该能够维持这种状态,但真实的代码库并不一定能达到这种理想状态。我们将在后面的部分中对此进行详细介绍。

视觉测试

进行视觉测试时,需要截取网站状态的屏幕截图或视频,以便对照当前测试运行来检查已知良好的状态(例如之前的屏幕截图)。本质上,它要求运行真实的浏览器,以便呈现 HTML、CSS 以及网站的其他部分。

构建仅渲染特定组件(尤其是在不同尺寸的屏幕上触发响应式界面)的 HTML“自动化测试框架”会很有用,而不是直观地测试运行整个代码库的端到端测试。这比纯粹使用 JSDOM 或类似框架更复杂。

目视测试失败可能是表明其他类型故障的正常信号。但是,复杂的界面可能会因与您尝试测试的功能无关的原因而未通过视觉测试,例如其他会改变界面外观的新功能,甚至新的操作系统版本呈现的表情符号与早期版本不同。

端到端测试

端到端测试通常位于测试金字塔的顶端。它们描述的是与您的 Web 应用或网站的完整体验交互,可能以特定功能为中心,并且通常在由 WebdriverIO、Selenium 或 Puppeteer 等代理控制的浏览器中运行,这些代理的运行程度有别于生产环境中部署的代码库(尽管通常在 localhost 上提供)。

这可能涉及以测试用户身份登录、执行主要操作,以及确认您的网站或系统是否处于正确状态,具体取决于您的网站。我们将在后续部分中介绍更多此类测试的示例,因为它们可能非常强大,但有时难以维护。

用于简化这些组件的一些策略可以包括缩小其范围,或模拟相关组件的特定组件。例如,如果用户需要登录您的网站,但登录不是您要测试的功能,您可能需要为测试环境设置一个标志,让测试控制器无需登录或创建关联 Cookie 即可直接执行操作。

虽然端到端测试是一种非常强大的方法,可以同时对代码库的大量跨部分进行测试,但此类大规模测试由于依赖于外部系统,因此存在不稳定或不可靠的风险。它们通常还会在数据库中留下大量测试数据,例如,如果每次测试都创建或修改一个条目。累积这样的剩余数据可能会导致难以确定测试如何失败。

API 测试

API 测试可以指确认您的软件提供的 API 的行为,或访问实际(可能是实时)API 以确认其行为。无论采用哪种方式,这种方法都倾向于测试系统之间的抽象(它们最终如何相互通信),而不像在集成测试中那样将它们实际集成在一起。

这些测试可以提供集成测试的基本先决条件,而无需在运行要测试其间连接的系统时产生开销。但是,实际系统测试可能不稳定。

其他类型

还有各种其他测试方法可能很有用,具体取决于您的来源。有趣的示例如下:

  • 手动测试。
  • 验收测试是 Agile 广泛采用的一种手动测试,用于确认产品“满足用户的需求”。
  • 混乱测试是指输入随机数据,看看会发生什么,确保在输入错误数据后网站不会崩溃。
  • 故障测试会有意模拟复杂系统中的故障(如网络故障),以确保被测代码以可控方式响应。
  • build 测试通过检查代码库的 build 工件是否存在或其内容来确认其是否可以生成。此测试类型对于检查复杂 CMS 的输出非常有用。

代码覆盖率

可以衡量自动化测试所测试的代码百分比,并随时间将此情况作为统计数据报告。我们不建议实现 100% 的代码覆盖率,因为这可能会导致不必要的开销,以及无法深入涵盖主要用例的过于简单或设计不佳的测试。

在编写或测试测试(尤其是集成测试)时,覆盖率本身也可能是一个很有用的工具。通过显示单个测试所测试代码的百分比或逐行细分,您可以深入了解缺少的内容或接下来可测试的内容。

资源

检查您的掌握程度

以下哪些是已知的测试类型?

视觉测试
混乱测试
火灾测试
如果您正在为消防部门开发软件,则可能会用到。
差异测试
压力测试
我们在这里未提到过,但是压力测试或负载测试是一种测试生产系统,可确保它们能够接受大量流量。它与大型系统设计相关,而不是测试更典型的代码库。