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

我知道所谓的单元测试和集成测试的教科书定义。 我很好奇的是什么时候编写单元测试的时候......我会写它们来尽可能多地包含类。

举例来说,如果我有一个Word类,我会写的一些单元测试Word类。 然后,我开始写我的Sentence类,并且当它需要与Word类交互时,我会经常编写我的单元测试,以便他们测试SentenceWord ...至少在他们交互的地方。

有这些测试基本上成为集成测试,因为他们现在测试这两个类的集成,还是仅仅是一个跨越两个类的单元测试?

一般来说,由于这种不确定的线路,我很少会真正编写集成测试......或者我正在使用成品来查看所有的部分是否能够正确运行实际的集成测试,即使它们是手动的,很少重复超出范围每个人的特征?

我是否误解了集成测试,还是集成测试和单元测试之间真的差异很小?


编辑

感谢所有人的回应! 我认为,从各种不同的答案中可以明显看出,单元测试和集成测试之间的界限绝对是一条模糊的线条,可能试图找出哪些是真正的焦点应该停留在代码上,这可能有些迂腐(谢谢@Rob Cooper )。 另外,抱歉,我不会接受任何答案,因为太多太棒了,而且看起来确实很主观。


对我而言,主要区别在于集成测试可以揭示功能是工作还是中断,因为它们会在接近实际的场景中强调代码。 他们调用一个或多个软件方法或功能,并测试它们是否按预期行事。

相反,测试单一方法的单元测试依赖于其他软件正常工作(通常是错误的)的假设,因为它明确地嘲笑每个依赖。

因此,当执行某项功能的方法的单元测试为绿色时,并不表示该功能正在运行。

假设你有一个这样的方法:

public SomeResults DoSomething(someInput) {
  var someResult = [Do your job with someInput];
  Log.TrackTheFactYouDidYourJob();
  return someResults;
}

DoSomething对您的客户非常重要:这是一个功能,唯一重要的事情。 这就是为什么你通常写一个声明它的Cucumber规范:你希望验证和通信该功能是否工作。

Feature: To be able to do something
  In order to do something
  As someone
  I want the system to do this thing

Scenario: A sample one
  Given this situation
  When I do something
  Then what I get is what I was expecting for

毫无疑问:如果测试通过,您可以断言您正在提供工作特性。 这就是你可以称之为商业价值。

如果你想为DoSomething编写一个单元测试,你应该假装(使用一些模拟)其余的类和方法正在工作(即:该方法正在使用的所有依赖项都正常工作)并声明你的方法正在工作。

在实践中,你可以这样做:

public SomeResults DoSomething(someInput) {
  var someResult = [Do your job with someInput];
  FakeAlwaysWorkingLog.TrackTheFactYouDidYourJob(); // Using a mock Log
  return someResults;
}

你可以使用依赖注入,或者某个工厂方法或者任何模拟框架,或者只是扩展被测试的类。

假设Log.DoSomething()存在一个错误。 幸运的是,Gherkin规范会发现它,并且您的端到端测试将失败。

该功能不起作用,因为Log已损坏,而不是因为[Do your job with someInput]没有完成其工作。 顺便说一下, [Do your job with someInput]是该方法的唯一责任。

另外,假设Log在100个其他特征中使用,在100个其他类别的100个其他特征中使用。

是的,100个功能将失败。 但幸运的是,100个端到端测试也失败了,并揭示了这个问题。 而且,是的,他们说的是实话。

这是非常有用的信息:我知道我有一个坏的产品。 这也是非常令人困惑的信息:它没有告诉我什么问题在哪里。 它告诉我症状,而不是根本原因。

然而, DoSomething的单元测试是绿色的,因为它使用了一个伪造的Log ,永远不会中断。 而且,是的:它显然在说谎。 这是沟通一个破碎的功能正在工作。 它如何有用?

(如果DoSomething()的单元测试失败,请确保: [Do your job with someInput]是否存在一些错误。)

假设这是一个破坏类的系统: 一个破碎类的系统

一个bug会破坏几个功能,几个集成测试将会失败。

一个bug会破坏几个功能,几个集成测试将会失败

另一方面,同样的错误只会打破一个单元测试。

同样的错误只会打破一个单元测试

现在,比较两种情况。

同样的错误只会打破一个单元测试。

  • 所有使用损坏Log都是红色的
  • 所有的单元测试都是绿色的,只有Log的单元测试是红色的
  • 实际上,所有使用中断功能的模块的单元测试都是绿色的,因为通过使用mock,他们移除了依赖关系。 换句话说,他们运行在一个理想的,完全虚构的世界。 这是隔离错误并寻找它们的唯一方法。 单元测试意味着嘲笑。 如果你不嘲笑,你不是单元测试。

    区别

    集成测试告诉什么不起作用。 但是他们在猜测问题出在哪里并没有用。

    单元测试是唯一能够告诉你错误发生在哪里的测试。 要绘制这些信息,他们必须在模拟环境中运行该方法,其中所有其他依赖关系都应该正常工作。

    这就是为什么我认为你的句子“或者它只是一个跨越两个班的单元测试”而被忽略了。 单元测试不应该跨越2个类。

    这个回复基本上是我在这里写的东西的总结:单元测试谎言,这就是为什么我爱他们。


    当我编写单元测试时,我将测试代码的范围限制为我正在通过嘲笑依赖关系来编写的类。 如果我正在写一个Sentence类,并且Sentence对Word有依赖性,我将使用一个模拟Word。 通过嘲弄Word,我只能关注它的界面,并测试我的Sentence类的各种行为,因为它与Word的界面交互。 这样我只测试句​​子的行为和实现,而不是同时测试Word的实现。

    一旦我编写了单元测试以确保Sentence基于Word界面与Word进行交互时的行为正确,然后我编写集成测试以确保我对交互的假设是正确的。 为此,我提供实际的对象并编写一个测试,练习一个将最终使用句子和单词的功能。


    我的10位:D

    我总是被告知单元测试是对单个组件的测试 - 应该充分运用它。 现在,这往往有很多层次,因为大多数组件都是由较小的零件组成。 对我而言,一个单位是系统的一个功能部分。 所以它必须提供一些有价值的东西(即不是用于字符串解析的方法,而是HtmlSanitizer)。

    集成测试是下一步,它采取一个或多个组件,并确保它们一起工作,因为它们应该是这样。然后,您就会担心组件单独工作的复杂性,但是当您将HTML输入到HtmlEditControl中时,它不知何故神奇地知道它是否有效。

    尽管它是一个真正的可移动的线..我宁愿更多地关注让该死的代码完全停止^ _ ^

    链接地址: http://www.djcxy.com/p/39647.html

    上一篇: What is the difference between integration and unit tests?

    下一篇: Profiling DLL/LIB Bloat