集成测试和单元测试有什么区别?

353

我知道所谓的单元测试和集成测试的教科书定义。 但我想知道的是什么时候该写单元测试…… 我会尽可能多地编写单元测试来覆盖许多类集。

例如,如果我有一个Word类,我会为Word类编写一些单元测试。 然后,我开始编写我的Sentence类,当它需要与Word类交互时,我通常会编写我的单元测试,以便它们同时测试SentenceWord ... 至少在它们相互作用的地方。

这些测试是否已经成为集成测试,因为它们现在测试了这两个类的集成,或者它只是跨越2个类的单元测试?

一般而言,由于这种不确定性,我很少编写实际的集成测试……或者说,使用成品来查看所有组件是否正常工作就是实际的集成测试,即使它们是手动的,并且很少超出每个单独功能的范围重复。

我是否误解了集成测试,或者集成和单元测试之间真的没有太大区别?

21个回答

4

我认为,如果class1的单元测试测试了class1的功能,class2的单元测试测试了class2的功能,并且它们没有访问数据库,那么即使这两个类相互作用,我仍然会将它们称为单元测试。

当测试运行大部分堆栈甚至访问数据库时,我将其称为集成测试。

我真的很喜欢这个问题,因为TDD讨论有时对我来说感觉过于纯粹,看到一些具体的例子对我很有好处。


4
我也是这样做的 - 我把它们都称为单元测试,但在某些时候,我有一个“单元测试”覆盖了很多,我经常将其重命名为“..IntegrationTest” - 只是名称更改,没有其他变化。
我认为从“原子测试”(测试一个小类或方法)到单元测试(类级别)再到集成测试,然后是功能测试(通常从上到下覆盖更多内容)存在连续性 - 没有清晰的分界线。
如果你的测试设置数据,并且可能加载数据库/文件等,则可能更像是集成测试(我发现集成测试使用较少的模拟和更多的真实类,但这并不意味着您不能模拟一些系统)。

4

集成测试:测试数据库持久性。
单元测试:模拟数据库访问。测试代码方法。


3

用类比进行简单解释

这篇答案将完全专注于例子。

集成测试

集成测试检查所有的东西是否协同工作。

单元测试

它们告诉你一个具体的东西是否在工作。

例子

考虑一辆汽车:

  • 汽车的集成测试:例如,汽车是否能够开到本地(Pondicherry)并返回?如果可以,整个汽车正在工作。如果失败,你不会真正知道原因。是散热器、传动装置、引擎还是化油器出了问题?

  • 汽车的单元测试:引擎是否在工作?这只测试引擎,没有测试其他任何部分。如果这个测试失败了,那么你可以确信引擎中有一个错误.......这与“伪造”这个概念密切相关。您可能需要一些钥匙才能启动发动机 - 除了,您不想麻烦进行实际的点火(有锁).....相反,您会使用 “假” 钥匙来启动它。

同样地,在单元测试中,您可以使用“模拟对象”来使引擎按特定方式工作。然后你只需要测试:“它是否在运行”。

3

单元测试是针对一个工作单元或者一段代码进行的测试。通常由单个开发人员执行。

集成测试是指在开发人员将其代码提交到源代码控制库时,最好在集成服务器上执行的测试。集成测试可以由诸如Cruise Control之类的工具执行。

因此,您需要进行单元测试来验证您构建的工作单元是否正常工作,然后进行集成测试以验证您添加到存储库中的任何内容是否破坏了其他功能。


2
我称白盒测试类的测试为单元测试。该类所需的任何依赖项都将被替换为虚拟的(模拟)。
集成测试是测试多个类及其交互的测试。在这种情况下,只有一些依赖关系是虚拟/模拟的。
除非其中一个依赖项是真实的(即未伪造),否则我不会将控制器视为集成测试(例如,IFormsAuthentication)。
将这两种类型的测试分开对于在不同级别测试系统很有用。此外,集成测试往往具有长寿命,而单元测试应该快速。执行速度的差异意味着它们以不同的方式执行。在我们的开发过程中,单元测试在提交时运行(因为它们很快),而集成测试每天运行一两次。我尽可能经常运行集成测试,但通常会减慢打开数据库/写入文件/进行rpc等速度。
这引出了另一个重要的观点,单元测试应避免使用IO(例如磁盘、网络、数据库)。否则,它们会变得非常缓慢。消除这些IO依赖关系需要一些努力 - 我不能承认我一直遵守“单元测试必须快速”的规则,但如果您遵守这一规则,则在更大的系统上很快就会看到好处。

1
此外,需要记住的是单元测试和集成测试都可以使用例如 JUnit 来自动化编写。在 JUnit 集成测试中,我们可以使用 org.junit.Assume 类来测试环境元素(如数据库连接)或其他条件的可用性。

1
这些测试基本上已经变成了集成测试,因为它们现在测试了这两个类的集成吗?还是说这只是跨越两个类的单元测试?
我认为是的,也是的。你的跨越两个类的单元测试已经成为了一个集成测试。
您可以通过使用模拟实现 - MockWord类来避免这种情况,这对于那些足够大,需要不同开发者实现的系统部分非常重要。在这种情况下,Word是单独进行单元测试的,Sentence是借助MockWord进行单元测试的,然后Sentence与Word进行集成测试。
真正的区别示例如下: 1)100万个元素的数组很容易进行单元测试,并且运行良好。 2)BubbleSort在模拟了10个元素的数组之后很容易进行单元测试,也可以正常工作 3)集成测试显示某些方面并不理想。
如果这些部分由单个人开发,则最有可能在单元测试BubbleSoft时发现问题,因为开发人员已经拥有了真正的数组,他不需要模拟实现。

1
这个问题有点学术化,不是吗?;-) 我的观点: 对我来说,集成测试是整个部分的测试,而不仅仅是其中两个部分是否配合。 我们的集成测试显示了包含40个项目的主构建是否成功。 对于项目,我们有大量的单元测试。 关于单元测试,对我来说最重要的是一个单元测试不应该依赖于另一个单元测试。因此,如果它们是独立的,那么你描述的这两个测试都是单元测试。对于集成测试,这并不重要。

1
我经常在面试中被问到这个问题。直到现在,我才会夸夸其谈我的专业知识,并且对组件和验收测试进行演讲。
多年来,我只理解了集成测试和单元测试。作为一个独立开发者,我可以编写单元测试,但并不总是费心去做。
单元测试
这是一个关键的区别。单元测试很容易实现和执行,理想情况下不需要依赖。这就是模拟的作用。通常情况下,不必模拟所有东西,特别是当你获得了其他函数的覆盖率时。也许更容易,但这不是单元测试的目的。
我要重申的是,单元测试应该易于运行和小型化。它们的失败提供了立即洞察到引入错误的位置。
以下是测试的层次结构,从底部的廉价和充足到顶部的慢、昂贵和少:

hierarchy of test expense and breadth.

可以概念化几个更多层,但为了清晰起见被省略了。

集成测试

通过集成测试,您将考虑引入严重的外部依赖项,例如VM、虚拟网络和设备。如果成本有保证,可能会使用实际的调制解调器、路由器和防火墙。

这些将不在本地运行,而是在构建服务器上运行。本地Jenkins和基于云的CI提供商的混合使用可满足此需求。

其他测试术语

这是我在业界服务了数年的理解。我们可以谈论组件测试并给出定义,但如果定义不在常规流通中,则失去了价值。

验收测试是我们所说的业务单元或客户要求。这些将引导一切方向并位于金字塔顶部(想象一个美元符号)。

E2E或端到端测试与集成测试通用,但我在网上注意到它位于之上。我猜它对验收测试比对集成测试更有关联,后者往往会更详细,对利益相关者的兴趣较小(尽管在部门内部极感兴趣)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接