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

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

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

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

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


当前回答

在我看来,答案是“为什么这很重要?”

是不是因为您只做单元测试而不做集成测试?反之亦然?当然不是,你应该尝试两者兼得。

是因为单元测试需要快速、隔离、可重复、自我验证和及时,而集成测试不需要吗?当然不是,所有的测试都应该是这样。

这是因为您在单元测试中使用模拟,而在集成测试中不使用它们吗?当然不是。这意味着,如果我有一个有用的集成测试,我不允许为某些部分添加模拟,担心我将不得不将我的测试重命名为“单元测试”或将其交给另一个程序员来处理。

是不是因为单元测试测试一个单元,而集成测试测试许多单元?当然不是。这有什么实际意义呢?关于测试范围的理论讨论在实践中无论如何都是行不通的,因为术语“单元”完全依赖于上下文。在类级别上,单元可能是一个方法。在程序集级别上,单元可能是类,而在服务级别上,单元可能是组件。 甚至类也会使用其他类,那么哪个是单位呢?

这无关紧要。

测试很重要,F.I.R.S.T也很重要,对定义吹毛求疵是浪费时间,只会让测试新手感到困惑。

其他回答

我认为,当您开始考虑集成测试时,您更多地是在谈论物理层之间的交叉,而不是逻辑层之间的交叉。

例如,如果您的测试只关心生成内容,那么它就是一个单元测试:如果您的测试只关心写入磁盘,那么它仍然是一个单元测试,但是一旦您同时测试了I/O和文件的内容,那么您就有了一个集成测试。当您在服务中测试函数的输出时,这是单元测试,但一旦您进行服务调用并查看函数结果是否相同,那么这就是集成测试。

从技术上讲,你不能只对一个类进行单元测试。如果您的类是由其他几个类组成的呢?这会自动地使它成为一个集成测试吗?我不这么想。

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

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

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

单元测试使用模拟

您正在讨论的是集成测试,它实际上测试了系统的整个集成。但是当你做单元测试时,你应该分别测试每个单元。其他一切都应该被嘲笑。在你的Sentence类的例子中,如果它使用了Word类,那么你的Word类应该被嘲笑。这样,您将只测试您的Sentence类功能。

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

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

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

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

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

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