使用 Go 语言进行测试的正确包命名

我在 Go 中看到了几种不同的测试包命名策略,想知道每种策略的优缺点,以及我应该使用哪种策略。

策略1:

文件名: github.com/user/myfunc.go

package myfunc

测试文件名: github.com/user/myfunc_test.go

package myfunc

有关示例,请参见 Bzip2

策略二:

文件名: github.com/user/myfunc.go

package myfunc

测试文件名: github.com/user/myfunc_test.go

package myfunc_test


import (
"github.com/user/myfunc"
)

有关示例,请参见 电线

策略3:

文件名: github.com/user/myfunc.go

package myfunc

测试文件名: github.com/user/myfunc_test.go

package myfunc_test


import (
. "myfunc"
)

有关示例,请参见 绳子

Go 标准库似乎混合使用了策略1和策略2。我应该使用这三者中的哪一个?将 package *_test附加到我的测试包中是一件痛苦的事情,因为这意味着我不能测试我的包私有方法,但是也许有一个我没有意识到的隐藏优势?

45691 次浏览

您应该尽可能使用策略1。您可以使用特殊的 foo_test包名来避免导入周期,但是大多数情况下导入周期都存在,因此可以使用相同的机制测试标准库。例如,strings不能用策略1进行测试,因为 testing包依赖于 strings。正如您所说的,在策略2或策略3中,您不能访问包的私有标识符,所以除非必要,否则最好不要使用它。

这取决于测试的范围。高级测试(集成、验收等)。.)应该放置在一个单独的包中,以确保您正在通过导出的 API 使用该包。

如果您有一个包含许多内部组件的大型软件包,需要进行测试,那么对于您的测试使用相同的软件包。但这并不是邀请您的测试访问任何私有状态。那将使重构成为一场噩梦。我经常实现接口。我从测试中调用的是那些接口方法,而不是所有单独的辅助方法/函数。

您所列出的三种策略之间的根本区别在于测试代码是否与被测试代码在同一个包中。在测试文件中使用 package myfuncpackage myfunc_test的决定取决于您想要执行 白盒子还是 黑匣子测试。

在一个项目中同时使用这两种方法并没有什么错。例如,你可以使用 myfunc_whitebox_test.gomyfunx_blackbox_test.go

测试代码包比较

  • 黑盒测试: 使用 package myfunc_test,这将确保您只使用 导出的标识符
  • 白盒测试: 使用 package myfunc以便您可以访问未导出的标识符。适用于需要访问非导出变量、函数和方法的单元测试。

上市公司竞争策略比较

  • 策略1: 文件 myfunc_test.go使用 package myfuncー在这种情况下,myfunc_test.go中的测试代码将与在 myfunc.go中测试的代码在同一个包中,在本例中是 myfunc
  • 策略2: 文件 myfunc_test.go使用 package myfunc_testーー在这种情况下,myfunc_test.go中的测试代码“将被编译为一个单独的包,然后与主测试二进制文件链接并运行。”[ Source: 第58-59行在 测试,开始源代码中]
  • 策略3: 文件 myfunc_test.go使用 package myfunc_test但是使用点符号导入 myfuncー这是策略2的一个变体,但是使用点符号导入 myfunc

关于 戈兰代码评论中的 import .,我想补充一个重要的注意事项:

由于 圆形的的依赖性,import .表单在测试中非常有用, 不能成为正在测试的包的一部分:

package foo_test


import (
"bar/testutil" // also imports "foo"
. "foo"
)

在这种情况下,测试文件不能在包 foo 中,因为它使用 所以我们使用‘ import.’表单来让文件 假装是包裹的一部分,即使它不是。

除了这一种情况,不要在程序中使用 import . 。 它使程序更难读,因为它不清楚是否一个名称 像 Quux 是当前包或导入包中的顶级标识符。