我知道所谓的单元测试和集成测试的教科书定义。我好奇的是什么时候该写单元测试了……我将写它们来覆盖尽可能多的类集。

例如,如果我有一个Word类,我将为Word类编写一些单元测试。然后,我开始编写我的Sentence类,当它需要与Word类交互时,我经常会编写单元测试,这样它们就可以同时测试Sentence和Word……至少在他们相互作用的地方。

这些测试本质上变成集成测试了吗?因为它们现在测试这两个类的集成,还是仅仅是一个跨越两个类的单元测试?

一般来说,由于这条不确定的界线,我很少实际编写集成测试……或者我是否使用成品来查看所有部件是否正常工作,即实际的集成测试,即使它们是手动的,并且很少在每个单独的功能范围之外重复?

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


当前回答

在单元测试中,你要测试每个独立的部分:

在集成测试中,您将测试系统的许多模块:

这是当你只使用单元测试时发生的事情(通常两个Windows都可以工作,不幸的是不能一起工作):

来源: source1 source2

其他回答

我也这么做——我把它们都称为单元测试,但在某些时候,我有一个“单元测试”,它涵盖了太多内容,我经常把它重命名为“..IntegrationTest”——只是名字改变了,其他的都没有改变。

我认为从“原子测试”(测试一个微小的类或方法)到单元测试(类级别)和集成测试——然后是功能测试(通常从上到下覆盖了更多的东西)——有一个延续——似乎没有一个干净的分界线。

如果您的测试设置了数据,可能还加载了数据库/文件等,那么它可能更像是一个集成测试(我发现集成测试使用更少的模拟和更多的真实类,但这并不意味着您不能模拟出系统的某些部分)。

如果class1的单元测试是测试class1的特性,而class2的单元测试是测试它的特性,并且它们不访问数据库,我想我仍然会把两个相互作用的类称为单元测试。

当一个测试运行了我的堆栈的大部分,甚至到达数据库时,我把它称为集成测试。

我真的很喜欢这个问题,因为TDD讨论有时对我来说有点太纯粹了,看到一些具体的例子对我来说是件好事。

类比的简单解释

上面的例子已经很好了,我就不再重复了。所以我会用例子来帮助你们理解。

集成测试

集成测试检查是否一切都在一起工作。想象一下手表上的一系列齿轮一起工作。一个综合测试是:手表是否显示正确的时间?它还能在3天内显示正确的时间吗?

它只告诉你整个部件是否正常工作。如果它失败了:它不会告诉你它到底在哪里失败。

单元测试

这些都是非常具体的测试类型。它们告诉你一件具体的事情是有效还是失败。这种类型的测试的关键是,它只测试一个特定的东西,同时假设其他一切都正常工作。这是关键。

例子: 让我们用一个例子来详细说明这一点:

Let’s take a car as an example. Integration test for a car: e.g. does the car drive to Woop Woop and back? If it does this, you can safely say that a car is working from an overall view point. It is an integration test. If it fails you have no idea where it is actually failing: is it the radiator, transmission, engine, or carburettor? You have no idea. It could be anything. Unit test for a car: Is the engine is working? This tests assumes that everything else in the car is working just fine. That way, if this particular unit test fails: you can be very confident that the problem lies in the engine – so you can quickly isolate and fix the problem.

使用存根

假设您的汽车集成测试失败。它不能成功地开到埃丘卡。问题出在哪里? 现在让我们假设你的发动机使用一个特殊的燃油喷射系统,这个发动机单元测试也失败了。换句话说,集成测试和发动机单元测试都失败了。那么问题在哪里呢?(给自己10秒钟的时间来回答。) 是发动机出了问题,还是燃油喷射系统出了问题?

你看到问题了吗?你不知道什么是失败。如果你使用不同的外部依赖关系,那么这10个依赖关系中的每一个都可能导致问题——你不知道从哪里开始。这就是为什么单元测试使用存根来假设其他一切都正常工作。

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

集成测试是指当开发人员将其代码提交到源代码控制存储库时,最好在集成服务器上执行的测试。集成测试可以由Cruise Control等实用程序执行。

因此,您可以执行单元测试来验证您构建的工作单元是否正常工作,然后集成测试验证您添加到存储库中的任何内容都没有破坏其他内容。

我在采访中经常被问到这个问题。到目前为止,我一直在吹嘘我的专业知识,并对组件测试和验收测试侃侃而谈。

多年来,我只了解集成和单元测试。作为一个单独的开发人员,我可以编写单元测试来磨练我的技能,但我并不总是这么做。

单元测试

这是一个关键的区别。单元测试易于实现和执行,理想情况下不需要依赖。这就是嘲笑的意义所在。不模仿所有内容通常更容易,特别是在覆盖您所编写的其他函数的情况下。也许更简单,但这不是单元测试的思想。

我要重申,单元测试意味着易于运行且规模小。它们的失败可以让我们立即了解bug是在哪里引入的。

下面是测试的等级,从底部的廉价和丰富到顶部的缓慢、昂贵和很少:

还有几个层可以概念化,但为了清晰起见,省略了这些层。

集成测试

通过集成测试,您可以考虑引入严重的外部依赖项,例如虚拟机、虚拟网络和设备。可能您可以使用实际的调制解调器、路由器和防火墙,只要这些花费是合理的。

这些不会在本地运行,而是在构建服务器上运行。本地Jenkins和基于云的CI提供商的组合满足了这一需求。

其他测试术语

这是我在工业界工作了几年的体会。我们可以讨论组件测试,并得到一个定义,但如果这个定义没有被广泛使用,那么它就失去了价值。

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

端到端测试是集成测试的同义词,但我在网上注意到它被放在上面。我想它可能与验收测试和集成测试更相关,后者往往更详细,涉众的兴趣更少(尽管部门内部有巨大的兴趣)。