集成测试
2018年1月16日
集成测试确定独立开发的软件单元在相互连接时是否能正常工作。这个术语甚至在软件行业模糊的标准中也变得模糊不清,因此我在写作中一直谨慎使用它。特别是,许多人认为集成测试的范围必然很广,而实际上它们可以通过更窄的范围更有效地进行。
正如这些事情经常发生的那样,最好从一点历史开始。当我第一次了解集成测试时,是在 1980 年代,瀑布模型是软件开发思维的主导影响。在一个较大的项目中,我们会有一个设计阶段,它会指定系统中各个模块的接口和行为。然后将模块分配给开发人员进行编程。一个程序员负责一个模块并不罕见,但这个模块足够大,可能需要几个月才能构建。所有这些工作都是独立完成的,当程序员认为它完成时,他们会将其交给 QA 进行测试。
测试的第一部分将是单元测试,它将单独测试该模块,针对设计阶段完成的规范。一旦完成,我们就会进入集成测试,将各个模块组合在一起,要么组合成整个系统,要么组合成重要的子系统。
正如其名称所示,集成测试的目的是测试**多个独立开发的模块是否按预期协同工作**。它是通过激活多个模块并对所有模块运行更高级别的测试来执行的,以确保它们协同工作。这些模块可以是单个可执行文件的一部分,也可以是独立的。
从 2010 年代的视角来看,这些混淆了两个不同的东西
- 测试独立开发的模块是否能正常协同工作
- 测试多个模块组成的系统是否按预期工作。
这两件事很容易混淆,毕竟,除了将购物车和目录模块都激活到一个环境中并运行测试来测试这两个模块之外,你还能如何测试它们呢?
2010 年代的视角提供了另一种选择,这在 1980 年代很少被考虑。在这种选择中,我们通过测试购物车中与目录交互的那部分代码来测试购物车和目录模块的集成,将其针对目录的测试替身执行。如果测试替身是目录的忠实替身,那么我们就可以测试目录的所有交互行为,而无需激活完整的目录实例。如果它们是单体应用程序的独立模块,这可能不是什么大问题,但如果目录是一个独立的服务,则需要它自己的构建工具、环境和网络连接,这将是一个大问题。对于服务,此类测试可能会针对进程内测试替身运行,或者针对通过网络的替身运行,使用类似于mountebank的东西
使用针对替身的集成测试的一个明显问题是,该替身是否真正忠实。但是我们可以使用契约测试单独测试这一点。
使用这种结合了狭窄的集成测试和契约测试的方法,我可以确信自己可以针对外部服务进行集成,而无需针对该服务的真实实例运行测试,这极大地简化了我的构建过程。执行此操作的团队可能仍然会对所有真实服务进行某种形式的端到端系统测试,但如果是这样,它只是一个范围非常有限的路径测试的最终冒烟测试。拥有成熟的生产环境中的 QA功能也有帮助,如果它足够成熟,可能根本不需要进行端到端系统测试。
问题是我们至少对构成集成测试的两种不同概念。
狭窄的集成测试
- 只测试我服务中与独立服务通信的那部分代码
- 使用这些服务的测试替身,无论是在进程内还是远程
- 因此,它由许多范围狭窄的测试组成,通常范围不超过单元测试(并且通常使用与单元测试相同的测试框架运行)
广泛的集成测试
- 需要所有服务的实时版本,需要大量的测试环境和网络访问
- 测试所有服务的代码路径,而不仅仅是负责交互的代码
并且,有大量的软件开发人员认为“集成测试”只意味着“广泛的集成测试”,当他们遇到使用狭窄方法的人时,就会导致很多困惑。
如果你的集成测试只有广泛的测试,你应该考虑探索狭窄的风格,因为它可能会显著提高你的测试速度、易用性和弹性。由于狭窄的集成测试范围有限,它们通常运行速度非常快,因此可以在部署管道的早期阶段运行,如果它们变为红色,可以提供更快的反馈。
好像这种术语上的混乱还不够,在 2010 年代后期,“集成测试”又出现了另一种用法。这来自于单元测试含义的差异。有些人将单元测试定义为我所说的孤立单元测试,即所有除被测试者之外的程序元素都被替换为测试替身。鉴于这种狭窄的定义,一些作者将“集成测试”定义为社交单元测试。
这就是我为什么对“集成测试”持谨慎态度的原因。当我读到它时,我会寻找更多上下文,以便我知道作者真正指的是哪种。如果我谈论广泛的集成测试,我更喜欢使用“系统测试”或“端到端测试”。对于狭窄的集成测试,我没有更好的名称,所以我确实使用了它(但使用“狭窄”来帮助向读者表明这些测试的性质)。我继续对两种类型的测试都使用“单元测试”,在需要区分时使用孤立/社交。
致谢
Birgitta Böckeler、Brian Oxley、Dave Rice、Deepti Mittal、Jonny Leroy、Kief Morris、Raimund Klein、Rogerio Chaves 和 Tiago Griffo 在我们的内部邮件列表中讨论了这篇文章的草稿。修订
2021 年 6 月 3 日更新,将“集成测试”的用法改为社交单元测试,从脚注移到正文中