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

问题描述 投票:0回答:2

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

似乎在业界,在谈论UT时,UT应该很小(范围),并且还模拟外部依赖。我不认为这是一种好的思维方式,因为这意味着我的UT可以错过IT捕获的错误,这意味着每隔几分钟只运行一次UT就不够好了,我应该运行IT测试,这要慢得多对我不好,因为重构过程会花费我更长的时间。

那么我错过了什么?为什么不编写那个像IT一样测试完整流程的UT,但是模拟外部依赖?谢谢

java unit-testing testing automated-tests integration-testing
2个回答
1
投票

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

该定义设置了单元测试范围的下限,即从最小的软件开始。对于上限,它留下了一定的自由度。有时人们试图通过提出术语单位的定义来界定上限。但是,我并不在乎单位是什么。相反,我根据被测软件的大小来设置限制,使得单元测试方法仍然可以合理应用。

例如:15行代码的单个函数将进行单元测试。但是,如果我重构我的代码,以便从函数中提取两个辅助函数呢?根据定义,我现在还可以对辅助函数应用单元测试。但是,如果我已经拥有了一套完美的单元测试,那么这些单元测试仍然适用于原始功能的界面。因此,我可以保留我的测试并忽略改变的内部结构 - 它仍然是单元测试。

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

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

再看一下上面的定义,它提到了隔离。但请注意,此处的隔离用于对可以找到的错误类型进行分类:单元测试用于查找可在隔离软件中找到的错误。它并未声明您在测试期间实际上必须隔离代码。换句话说,您不一定要模拟依赖项。

嘲笑应该是有原因的。如果您考虑模拟函数或方法,您应该知道要解决的问题。如果没有问题要解决,请不要嘲笑。例如,您也不会模拟标准库数学函数,例如sin或cos,因为它们在大多数情况下也不会导致问题。

例如,如果依赖于组件(DOC)导致非确定性行为(随机性,时间......),您可以进行模拟。但是,对于模拟,您无法找到这些错误,这些错误与被测函数与DOC的交互如何工作的误解有关:自实现模拟以来,您可以根据潜在的误解来实现它们。这不是单元测试的缺陷:这也是除了单元测试之外还需要集成和系统测试的原因。

摘要第2部分:单元测试不一定是关于模拟。它专注于寻找一种特殊的错误:如果代码被隔离,你可以找到它们。这使得所有其他错误(尤其是那些只能在集成软件中找到的错误)超出了单元测试的范围。


2
投票

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

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

一个区别是人们认为是一个单位。面向对象的设计倾向于将一个类视为单元,程序或功能方法可能将单个函数视为一个单元。但实际上这是一种情境性的事情 - 团队决定成为一个单位是有意义的,以便他们理解系统及其测试。虽然我从单元作为一个类的概念开始,但我经常采用一堆密切相关的类并将它们视为一个单元。我很少将一个方法的子集作为一个单元。但是你定义它并不重要(https://martinfowler.com/bliki/UnitTest.html

通常,您有单元测试,其中包含用于测试多个类/模块之间集成的小块代码和集成测试。而且,您进行单元测试的频率要高于IT测试。

小单元测试的目的是找到导致bug尽可能精确的代码片段。如果您使用多个类的It测试失败,那么您需要逐个检查所有这些类以查找问题。但是,如果您的单元测试覆盖了单一类的单一方法失败,那么您就知道问题究竟在哪里。

© www.soinside.com 2019 - 2024. All rights reserved.