我什么时候应该编写集成测试?


30

根据TDD的规则,单元测试是在生产代码之前编写的,但是,在具体(非模拟)有线对象之间进行交互的集成测试又如何呢?

它们应该在单元测试之前还是在生产代码之后编写,仅用于测试“接线”?

请注意,我不是在谈论验收或功能测试,而是在进行较低级别的集成测试。

Answers:


49

Rspec书以及其他BDD资源中提出了这样的循环:

在此处输入图片说明

本质上,该过程是:

While behaviour required
    Write an integration test for a specific behaviour
    While integration test failing
        Write a unit test to fulfil partial behavior
        While unit test failing
            Write code to make unit test pass
        Commit
        While refactoring can be done
            Refactor
            While unit test failing
                Write code to make unit test pass
            Commit
    Push

免责声明:毫无疑问,这可以带来最佳的代码和产品,但这可能很耗时。谈到集成测试应始终通过时,围绕数据和确定性存在各种困难。并非在所有情况下都适用;有时,您只需要把东西拿出来。

就是说,有一个理想的过程很重要。它为您提供了一个折中的起点。


2
感谢@pdr,但我指定我不是在谈论在迭代之前/开始编写的验收测试,我对较低级别的集成测试感兴趣。
Chedy2149 2013年

@ chedy2149:Akkh。错过了该评论。在删除答案之前,我认为您应该更具体地说明集成测试中“低级”的含义。
pdr

下层:开发人员期望用户或客户端未指定哪些行为,以及用于测试类/组件交互的行为。
Chedy2149

4
实际上,如果您在该图片中放置“验收测试”或“集成测试”,我认为这没有什么不同-它是在不同抽象级别上进行任何类型测试的理想视图。但是恕我直言,真正的问题不是这可能是“耗时的”-真正的问题是针对公共接口编写“预先”集成测试,而仍然需要借助TDD进行设计,就像在“移动目标”上射击一样”。
布朗

@DocBrown所以您的答案是在生产代码之后和发布之前?
Chedy2149

10

真实的项目向我展示了不可能编写单元测试,然后进行集成,甚至相反的方向也是错误的:-)因此,我通常将单元测试与集成一起编写。

为什么?让我写一下如何看待两种测试:

  1. 单元测试 -除了Wikipedia和所有已知信息外,单元测试还可以帮助您缩小设计范围,改善模型和关系。流程很简单:一旦您开始键入新项目/新组件,大多数时候您就在制作某种PoC。完成后,您将始终拥有长方法,长类,非连贯方法和类等。

    单元测试可帮助您消除这些问题,因为使用上述模拟(不依赖其他组件)类进行实际的单元测试时,是不可测试的。无法测试的代码的基本标志是测试的大型模拟部分,因为您被迫模拟许多依赖项(或情况)

  2. 集成测试 -正确且有效的测试告诉您您的新组件(一个或多个)可以协同工作或与其他组件一起工作-这是通常的定义。我发现集成测试主要可以帮助您定义流程,以便消费者方面使用组件

    这一点非常重要,因为有时它会告诉您,API从外部是没有意义的。

那么,一旦我以后编写单元测试和集成测试,会发生什么?

我得到了不错的类,清晰的设计,良好的构造函数,简短且一致的方法,支持IoC等。一旦将我的类/ API提供给某些使用者(例如来自集成或GUI团队的开发人员),他就无法使用我的API,因为这似乎不合逻辑, 奇怪的。他只是感到困惑。因此,我根据他的观点修复了API,但是它也需要重写许多测试,因为我被迫更改方法,有时甚至更改如何使用API​​。

好吧,一旦我以后写集成测试和单元测试,会发生什么?

我得到了确切的流程,良好的可用性。我还拥有大型类,非一致代码,无日志记录,长方法。意大利面代码

我有什么建议?

我了解了以下流程:

  1. 开发代码的基本框架
  2. 编写集成测试,从消费者的角度说这是否有意义。现在基本的用例就足够了。该测试显然无法正常工作。
  3. 为每个类编写代码以及单元测试。
  4. 编写其余/缺少集成测试的内容。最好在#3中实施这些测试,以改进代码。

请注意,我已经就单元/集成测试做了简短的介绍,请参见幻灯片#21,其中描述了框架。


5

单元测试用于测试应用程序中软件的最小可测试位并测试其功能。在将每个单元合并为应用程序的一部分或更大的组件之前,将分别测试每个单元。

这就是集成测试的用处:
在将这些零件装配在一起时,它们会测试这些新创建的零件,这些零件由先前测试的单元组成。最好的情况是在编写应用程序本身的同时编写测试。


那么您的答案是在生产代码之后?
Chedy2149

这不能回答问题。他在询问是否在编写集成测试之后编写生产代码。您的答案可以采用任何一种方式。
Reactgular

1
@MathewFoscarini-更新的答案。希望现在变得更加清晰。
Ben McDougall

关于单元测试,我会考虑“ 尽可能少的软件”。测试合同中包含的内容(例如,对象的公共方法,库的导出函数),因为合同定义了必须执行的操作。其他事情是可以测试的,但是这样做不仅浪费时间,而且适得其反。
itsbruce

3

我倾向于将集成测试视为与单元测试非常相似。在这种情况下,我将代码的子集视为黑匣子。因此,集成测试只是一个更大的盒子。

我更喜欢在生产代码之前编写它们。这样做的好处是可以帮助我记住尚未连接的部分,或者我稍微更改了对象交互中的细节。


有不同级别的测试:白盒组件测试,白盒集成组件测试。组件黑盒测试,集成黑盒测试。也有集成系统测试。
Alexander.Iljushkin

2

除了验收测试之外,我倾向于只在应用程序的边界编写集成测试,以验证其是否与第三方系统或组件很好地集成。

这个想法是创建适配器对象,该对象可以将第三方的语音转换为您的应用程序所需的内容,并针对真正的外部系统测试这些转换程序。我认为无论是先测试还是后测试,都没有常规单元测试那么重要,因为

  • TDD在这里提供的设计见解并不重要,因为设计是众所周知的,而且通常不会涉及任何复杂的事情,您只需将事物从一个系统映射到另一个系统即可。

  • 根据您要处理的模块/系统,它可能需要大量的探索,配置修改,样品数据准备,这需要时间,并且在短的TDD反馈循环中并不十分合适。

但是,如果您真的很乐意以很少的安全步骤逐步构建适配器,那么我绝对建议您先进行测试,这不会有任何伤害。

您可以在此处找到这种方法的示例:http : //davesquared.net/2011/04/dont-mock-types-you-dont-own.html(第6段) http://blog.8thlight.com/eric- smith / 2011/10/27 / thats-not-yours.html


在这里,您正在谈论验证“我们的系统”与第三方库之间的交互的集成测试,例如,在开发插件时如何针对平台测试交互?
Chedy2149

尽管我很少有插件开发经验,但我想它们可能会有所不同,因为它们本质上与主机应用程序紧密结合,因此您可能希望完全接受该集成,并决定不需要适配器层。在那种情况下,我会非常小心测试性能-根据主机应用程序的不同,直接在大量测试中调用其API可能非常慢。如果您担心这一点,则可以始终采用“附加的抽象层”方法,并在适配器上使用模拟+集成测试。
guillaume31

1

因此,我本来要接受第一个答案,但是它已被删除。
总结一下

  1. 编写单元测试
  2. 编写生产代码
  3. 编写集成测试以测试交互

在进行第1和第2步时请记住集成测试,以确保集成级别的可测试性。

集成测试不一定在步骤3端对端编写,而可以在步骤1和2之间部分编写。


3
这种总结完全忽略了过程的迭代性质。一旦生产代码的API达到一定程度的稳定,就可以开始编写集成测试。然后,您可以再次使用生产代码,并可能更改或扩展集成测试。因此,在大多数情况下,您不会“在生产代码后编写集成测试”,因此通常会在某种程度上并行执行这两项操作。实际上,这在很大程度上还取决于您正在使用哪种软件。“黑白”思维不会带您进一步。
布朗

很好。答案似乎忽略了通过重构进行设计的迭代本质。
Chedy2149

0

单元测试测试的代码离散的块内的项目。
集成测试测试您的代码与其他代码的接口方式:换句话说,它们测试您的代码的接口

在接口后面开发代码时编写单元测试。
开发接口或实现该接口的任何代码时,编写集成测试。

这意味着您有时会在项目的最后阶段编写集成测试,因为大多数工作都在接口后面:例如,编译器,实现多个逻辑层的特定Web服务或涉及很多工作的Web服务。内部逻辑。

但是,如果您要实现一组REST服务或重构数据模型并添加对XA事务的支持,那么您将几乎立即开始开发集成测试,因为您的大部分工作都是围绕接口进行的,无论它是REST API或程序如何使用数据模型。


您是否同意说单元测试是白盒测试,而集成测试是黑盒测试?
Chedy2149

不幸的是,这取决于。近年来(至少在Java世界中),集成测试技术已经取得了巨大的进步,因此我可以在一个应用服务器上测试1类。问题就变成了,单元测试和集成测试之间的界线在哪里?是在测试代码与其他技术的接口时进行的集成测试,还是在测试整个应用程序时进行的集成测试-不一定在要运行的环境中进行?
Marco Marco

简而言之,在某些情况下,请确保集成测试是黑盒测试,但并非在所有情况下都如此。
Marco Marco

仅供参考:Wiki将集成测试定义为“在软件测试中,将各个软件模块组合并作为一个整体进行测试的阶段”
Marco Marco

是的,Marco。每个组件级别都有集成。代码级别,应用程序级别,系统级别。
Alexander.Iljushkin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.