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

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

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

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

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


当前回答

A little bit academic this question, isn't it? ;-) My point of view: For me an integration test is the test of the whole part, not if two parts out of ten are going together. Our integration test shows, if the master build (containing 40 projects) will succeed. For the projects we have tons of unit tests. The most important thing concerning unit tests for me is, that one unit test must not be dependent on another unit test. So for me both test you describe above are unit tests, if they are independent. For integration tests this need not to be important.

其他回答

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

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

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

我把那些白盒测试类的测试称为单元测试。类需要的任何依赖项都被替换为伪依赖项(mock)。

集成测试是同时测试多个类及其交互的测试。在这些情况下,只有一些依赖关系是伪造的。

我不会调用Controller的集成测试,除非它们的依赖项之一是真实的(即不是伪造的)(例如IFormsAuthentication)。

Separating the two types of tests is useful for testing the system at different levels. Also, integration tests tend to be long lived, and unit tests are supposed to be quick. The execution speed distinction means they're executed differently. In our dev processes, unit tests are run at check-in (which is fine cos they're super quick), and integration tests are run once/twice per day. I try and run integration tests as often as possible, but usually hitting the database/writing to files/making rpc's/etc slows.

这引出了另一个重要的问题,单元测试应该避免碰到IO(例如磁盘、网络、db)。否则他们会慢很多。设计这些IO依赖需要一些努力——我不能承认我一直忠实于“单元测试必须是快速的”规则,但如果你是,在一个更大的系统上的好处很快就会显现出来。

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

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

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

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

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

这无关紧要。

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

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

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

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

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