单元测试定义-范围和模拟外部依赖项

时间:2018-09-18 13:25:12

标签: java unit-testing testing automated-tests integration-testing

我对重新定义单元测试的定义感到困惑。
我认为单元测试是关于模拟外部依赖关系的,范围可能像IT测试一样大(不止一个类)。 通过这种思维方式,我可以在UT的完整流程中进行测试,这可以帮助我快速地发现错误(我不使用Spring,不使用外部依赖项), 我想快速捕获错误,因为如果要进行重构,我希望每隔几分钟运行测试以查看是否损坏了,因此我需要快速运行测试。 (这就是为什么我只想运行UT而不是IT测试的原因。

在行业中,当谈论UT时,UT应该(作用域),并且还要模拟外部依赖性。 我认为这不是一个好方法,因为这意味着我的UT可能会错过IT捕获的错误,这意味着每隔几分钟仅运行UT是不够的,我应该运行速度较慢的IT测试,对我不利,因为重构过程将使我花费更长的时间。

那我还缺少什么?为什么不编写像IT一样测试完整流程但模拟外部依赖关系的UT? 谢谢

2 个答案:

答案 0 :(得分:2)

通常,单元测试是涵盖单个类的单个方法的测试。

  

在面向对象的程序设计中,单元通常是整个接口,例如类,但可以是单独的方法(https://en.wikipedia.org/wiki/Unit_testing

     

一个区别是人们认为是一个单位。面向对象的设计倾向于将类视为单元,过程或功能方法可能会将单个功能视为单元。但这确实是一种情况,团队出于对系统及其测试的理解而决定成为一个单元是有意义的。尽管我从单元是一类的概念开始,但我经常采用一堆紧密相关的类并将它们视为一个单元。我很少将类中方法的子集作为一个单元。但是,您定义的并不重要(https://martinfowler.com/bliki/UnitTest.html

通常,您有一些单元测试,这些单元测试涉及一小段代码,而集成测试则测试多个类/模块之间的集成。与IT测试相比,您运行单元测试的频率要高得多。

小型单元测试的目的是找到导致错误的代码段,使其尽可能精确。如果使用多个类的It测试失败,则需要逐个检查所有这些类以查找问题。但是,如果您覆盖单个类的单个方法的单元测试失败,那么您将确切知道问题出在哪里。

答案 1 :(得分:1)

定义:单元测试是一种测试方法,旨在发现或防止通过测试小型(甚至最小的)隔离软件段可检测到的错误。

此定义设置了单元测试范围的下限,即从最小的软件开始。对于上限,它留有一定的自由度。有时人们试图通过提出单位一词的定义来划定上限。但是,我不太在乎什么是单位。取而代之的是,我根据被测试的软件可以有多大以至于仍然可以合理地应用单元测试方法的问题来设置限制。

例如:一个功能,例如15行代码,将进行单元测试。但是,如果我重构我的代码,以便从该函数中提取两个辅助函数,该怎么办?根据定义,我现在还可以将单元测试应用于助手功能。但是,如果我已经有了一套完善的单元测试套件,那么它们仍然可以与原始功能的界面一起使用。因此,我可以保留测试,而忽略更改后的内部结构-仍然是单元测试。

另一个例子:在C ++中,容器类与相关的迭代器类一起出现。容器类及其对应的迭代器类紧密耦合。与单元测试方法一起测试这些类在许多情况下都可以很好地工作。在测试迭代器时,通常不会将其与容器类隔离开来,而是将它们一起测试-而且我仍然认为这是单元测试。

总结第1部分:,只要应用单元测试方法有意义,就可以将其应用于紧密耦合的函数集甚至紧密耦合的类。

再次看上面的定义,它提到隔离。但是请注意,此处的隔离用于对可以发现的错误的类型进行分类:单元测试用于发现可以在隔离的软件中找到的错误。它并没有说明您实际上必须在测试期间隔离代码。换句话说,您不必模拟依赖关系。

应该出于某种原因进行模拟。如果您考虑对函数或方法进行模拟,则应该知道要解决的问题。如果没有问题要解决,请不要嘲笑。例如,您也不要嘲笑sin或cos之类的标准库数学函数,因为它们在大多数情况下也不会引起问题。

例如,如果组件依赖(DOC)导致不确定的行为(随机性,时间等),您将进行模拟。但是,使用模拟程序时,您找不到那些错误,这些错误与对被测函数与DOC的相互作用应如何工作的误解有关:由于实施了模拟程序,因此要根据潜在的误解来实现它们。这不是单元测试的缺陷:这只是为什么除了单元测试之外,您还需要集成和系统测试的原因。

摘要第2部分:单元测试不一定与模拟有关。它着重于发现一种特殊的错误:如果代码是孤立的,您可以找到这些错误。这使所有其他错误(尤其是只能在集成软件中找到的错误)不在单元测试的范围内。