135

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

策略一:

文件名: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"
)

以电线为例。

策略三:

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

package myfunc

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

package myfunc_test

import (
    . "myfunc"
)

有关示例,请参见字符串。

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

4

4 回答 4

173

您列出的三种策略之间的根本区别在于测试代码是否与被测代码在同一个包中。使用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.gomyfunc在这个例子中。
  • 策略 2:文件myfunc_test.go使用package myfunc_test——在这种情况下,myfunc_test.go“将编译为单独的包,然后与主测试二进制文件链接并运行”中的测试代码。[来源:test.go源代码中的第 58-59 行]
  • 策略 3:文件myfunc_test.go使用package myfunc_testmyfunc使用点符号导入 - 这是策略 2 的变体,但使用点符号导入myfunc
于 2015-07-16T00:02:44.780 回答
21

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

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

于 2013-11-15T20:04:18.220 回答
12

您应该尽可能使用策略 1。您可以使用特殊的foo_test包名称来避免导入周期,但这主要是因为可以使用相同的机制测试标准库。例如,strings无法使用策略 1 进行测试,因为testing包依赖于strings. 正如您所说,使用策略 2 或 3 您无法访问包的私有标识符,因此通常最好不要使用它,除非您必须这样做。

于 2013-11-15T10:37:58.363 回答
0

我想import .Golang CodeReviewComments添加一个重要说明:

import .表单在由于循环依赖而不能成为被测试包的一部分的测试中很有用:

package foo_test

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

在这种情况下,测试文件不能在包 foo 中,因为它使用 bar/testutil导入 foo。所以我们使用'import'。形式让文件假装是包 foo 的一部分,即使它不是。

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

于 2020-07-29T11:14:15.513 回答