确定一个测试是单元测试还是集成测试。

5
所以我正在尝试决定为我的Python项目规划和组织测试套件的方式,但我对何时单元测试不再是单元测试有疑问,我希望能得到社区的一些反馈。
如果我理解正确:
- 单元测试测试代码的最小部分,例如只执行一个且仅执行一个简单操作的函数/方法,即使它有多个用例。 - 集成测试测试在相同上下文、环境等下执行两个或多个代码单元(但尽量将单元数量控制在最小范围内)是否良好地协同工作,而不仅仅是单独工作。
我的疑问是:假设我有一个简单的函数,它执行HTTP请求并返回此类请求的内容,无论是HTML、JSON等,都不重要,事实上这个函数非常简单,但从外部源请求信息,例如:
import requests

def my_function(arg):
    # do something very simple with `arg`, like removing spaces or the simplest thing you can imagine
    return requests.get('http://www.google.com/' + arg).content

现在这只是一个非常愚蠢的例子,但我的疑问是:
考虑到此函数正在从外部源请求信息,当您为其编写测试时,您仍然可以将此类测试视为单元测试吗?
更新:my_function()的测试将模拟对外部源的调用,以便它不依赖于网络/数据库/文件系统等,因此它是隔离的。但是,在运行时被测试的函数依赖于外部源,例如在生产中。
提前感谢!!:)
附注:当然,也许我没有完全理解单元测试和集成测试的目的,所以,如果我错了,请指出来,我会感激不尽。
3个回答

1

根据您的更新:

对于 my_function() 的测试将会使用存根来替代对外部资源的调用,这样就不会依赖于网络 / 数据库 / 文件系统等内容,从而使其更加隔离。但是,被测试的函数在运行时仍然依赖于外部资源(例如在生产环境中)。

只要在测试期间将外部依赖项存根化,那么您可以称之为单元测试。这是一种基于被测试单元在测试套件中的行为而非在生产环境中行为的单元测试。

根据您最初的问题:

考虑到此函数正在从外部源请求信息,当您为其编写测试时,您仍然可以将此类测试视为单元测试吗?

不行,任何与被测试单元相关或依赖于外部事物的代码的测试都是集成测试。这包括任何网页、文件系统和数据库请求的存在。

如果您的代码没有与其依赖项完全隔离,并且没有其他组件无法重现,则它是一个集成测试。

要正确进行单元测试,您需要模拟对 google.com 的调用。

使用调用google.com的代码,如果google崩溃或您失去了与互联网的连接,您的测试将失败(即测试不是100%隔离的)。如果google的行为发生变化,您的测试也会失败(即测试不是100%可重复的)。

嘿@mezoid,感谢您的回答。很抱歉我没有解释清楚。该函数依赖于外部源,但测试肯定会将该依赖关系存根化。我会更新我的问题 :) - Gerard
@Gerard 没问题。根据您更新的问题,我已经更新了我的回答。 - mezoid

0

我认为这不是一个集成测试,因为它没有使用应用程序的不同部分。该函数只做一件事情,可以称之为单元测试。

另一方面,这个特定的函数有一个外部依赖项,你不希望在测试中依赖于网络。这就是模拟会非常有帮助的地方。

换句话说,隔离函数并对其进行单元测试。

此外,进行集成测试,测试调用my_function()的应用程序部分的更高级方法。


我认为任何测试依赖于未被模拟的外部依赖项的代码都应该是集成测试。 - mezoid
@mezoid 我明白你的意思,但这里的“界限”非常明显。我的意思是,你需要将 my_function() 隔离开来,以确保这些是单元测试。而且,为 my_function() 的调用者编写的测试将被称为集成测试。谢谢! - alecxe
是的,我明白你的意思。 - mezoid
嘿,大家好,谢谢提供信息,很抱歉我之前缺乏信息。当然,我会使用模拟和类似的库来存根外部资源。我会更新我的问题 :) 对不起。 - Gerard
@Gerard 不错,但我提供的答案仍然相关。看一下。 - alecxe

0

你的代码是否在隔离环境中测试并不是区分单元测试和其他测试的标准。例如,你通常不会对标准库函数如sin(x)进行存根操作(除非在极少数情况下)。但是,如果你没有对sin(x)进行存根操作,这并不意味着你的测试就是集成测试。

什么情况下才算是集成测试?如果你的测试目标是在集成层次上发现错误,那么这个测试就是一个集成测试。也就是说,通过集成测试,你想要找出两个或多个组件之间的交互是否基于双方(或所有方)的相同假设。

然而,Mocking是一种正交技术,可以与几乎所有类型的测试结合使用。(但在集成测试中,你不能模拟你想要测试的交互的伙伴,但你可以模拟其他组件)。

由于Mocking通常需要一些努力,因此它必须带来一些好处,例如:

  • 显著加快测试速度
  • 即使某些软件部分尚未准备好或存在缺陷,也能进行测试
  • 测试在集成软件中难以设置的异常情况
  • 消除时间或随机性等不确定行为
  • ...

然而,如果模拟并不能解决实际问题,您最好直接使用所依赖的组件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接