2

我在一份新工作中开始了一个新项目。这是我第一次在 Python 中大量工作。与我必须在静态类型语言中跳过的箍相比,Mocking 是一种全新的野兽。我自己研究了团队的单元测试,并希望将其中一些从使用 Dingus 升级到 Mock。

今天早些时候,我遇到了一些检查转换类的测试。具体来说,它将十六进制数字字符串转换为 Mongo ObjectIds(唯一标识符)。我期望看到的是一个测试,验证给定一个有效的十六进制数,一个具有相同十六进制数的 ObjectId 将被返回 - 或者 - 如果一个错误的十六进制数会发生错误。相反,所有测试验证的是创建并返回了一个 ObjectId。事实上,ObjectId 被完全模拟出来了,十六进制数字也是如此!

现在,从字符串创建 ObjectId 不需要到服务器或任何东西。一切都在本地运行。

我和我的新同事询问了这个特殊的测试套件。他们的想法是,应该使用集成测试来验证实际的转换,并且作为单元测试,单元测试应该做的就是确保代码按预期从上到下流动,并创建并返回 ObjectId。所以,基本上,测试只验证这个类是否以预期的方式与环境交互。

我已经编写单元测试很长时间了。根据我的经验,我根本不会使用模拟,我只会验证转换是否按预期发生。这意味着与来自另一个模块的 ObjectId 类进行交互。也许我对单元测试的想法太笼统了。我一直保留用于连接到远程服务器、文件等的集成测试。

在我看来,在这个例子中使用 ObjectId 与使用 str 或 list 没有什么不同。当然,我可以模拟 str 和 list,但由于它们对我的代码所做的工作至关重要,所以在我看来,模拟它们没有多大意义。我唯一应该关心与依赖项交互的时候是它可以改变测试的结果。

编写简单检查代码流的单元测试有什么价值吗?单元测试不应该是验证代码行为/正确性的结果吗?

4

1 回答 1

1

因此,如果不查看代码,很难确切地看到发生了什么,但仅基于您的解释......

我会同意你的。行为才是重要的,而不是代码的流程。

如果以后有人需要更改代码流以支持不同的情况(例如,使用具有不同参数的函数来实现相同的结果)怎么办?他们可以在不破坏现有测试的情况下这样做。

如果您升级正在使用的库,而现在调用该函数实际上得到的结果与您想要的不同,该怎么办?您的测试仍然有效(正在调用该函数),但单元测试实际上试图测试的内容却没有。

真的,如何使用模拟和测试仍然是一个非常年轻的学科。关于单元测试(以及单元测试中使用的各种策略,例如模拟)是否被认为是“好东西”,目前尚无定论。然而,毫无疑问,我发现自己创建测试并不是为了实际测试行为,而是为了让我可以说我有测试,并且不正确地使用模拟是假装你已经创建了测试的好方法,而实际上你'刚刚创造了一种错误的成就感,即您的代码现在已经过更严格的测试。

于 2012-07-26T17:44:22.493 回答