Golang中是否应该专门导出函数以便进行单元测试?
Golang中是否应该专门导出函数以便进行单元测试? 我的包中有一个公共函数 F,它首先调用 GetX,然后调用 FilterY,最后返回过滤后的结果。
GetX 和 FilterY 都是公共的,因为我希望对它们进行全面的单元测试。但是,它们没有实际用途,我的包的任何用户都不太可能单独调用它们。只有 F 会被调用,这使得 GetX 和 FilterY 非常适合作为私有函数。
我是否应该仅仅为了单元测试而将这两个方法保持为公共?请记住,FilterY 中有一些复杂的逻辑,因此需要大量的单元测试用例。
这是可行的,不过你不能使用 package foo_test,而必须使用与被测试包相同的包名。
更多关于Golang中是否应该专门导出函数以便进行单元测试?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我正在一台macOS电脑上运行,会是这个原因吗?
go version
go version go1.15 darwin/amd64
如果你的 *_test.go 文件与包的源代码位于同一目录中,那么它们就是包本身的一部分,并且可以访问包中定义的所有函数,无论是公共的还是私有的。请查看 go/src 中的 Go 包本身。
当包被编译成其 .a 文件以供链接时,_test.go 文件会被忽略。请查看 go 源码目录中的 regexp 包:https://golang.org/src/regexp/。
这应该没有区别,但你有没有尝试过实际使用编译器来构建代码,还是仅仅依赖你的集成开发环境没有报错?
此外,以“测试模式”编译上述程序实际上是可行的,因为如果你也忽略测试文件,那么测试就不可能进行了……
clbanning:
如果包源文件与包源代码位于同一目录中,那么它们就是包本身的一部分,并且可以访问包中定义的所有函数,无论是公共的还是私有的。请查看Go语言本身的包。
你是在没有先尝试的情况下给出建议吗?这是我尝试的第一件事,但它不起作用。
我对这个说法表示怀疑。具体来说,我有一个文件 a.go 和一个文件 a_test.go,它们的第一行都是 package mypackage。如果我在 a_test.go 中定义一个非测试函数,我可以在 a.go 中调用它。
因此,我怀疑每次导入 mypackage 时,它不会导入 a_test.go 中导入的所有包。
嗨 @clbanning 和 @NobbZ,
这是一个非常奇怪的情况。我正在使用 Visual Studio Code 和 Go 1.14:
文件 a.go:
package a
func example() {
printSomething()
}
文件 a_test.go:
package a
import "fmt"
func printSomething() {
fmt.Println("something")
}
这运行得很好,没有编译错误。这里发生了什么?我甚至运行了一个测试,它确实打印了。
一个 *_test.go 文件,即使它与被测试的函数在同一个包中,也不会成为你最终交付产物的一部分。
go command - cmd/go - Go Packages
Go 是一个用于管理 Go 源代码的工具。
编译包时,构建工具会忽略以
_test.go结尾的文件。
*_test.go 文件与包源代码位于同一目录中,那么它们就是包本身的一部分,并且可以访问包中定义的所有函数。
您指的是将测试放在与代码相同的包中。从长远来看,这似乎是个坏主意,因为我不希望我的包的导入者在不知情的情况下导入任何仅用于测试的 sqlmock 或其他依赖项。
废话不多说……对我来说,下面的程序无法编译,因为 printer 不可用。
$ cat main.go
package main
import "./foo"
func main() {
foo.Print()
}
$ cat foo/print.go
package foo
func Print() {
printer()
}
$ cat foo/print_test.go
package foo
import "fmt"
func printer() {
fmt.Println("Foo")
}
$ go run main.go
# _/tmp/tmp.zQApmyskok/foo
foo/print.go:4:2: undefined: printer
所以,随你怎么称呼它。在你证明 _test.go 文件中的函数会泄漏之前,我相信文档。如果你确实能证明存在泄漏,那么这值得提交一个错误报告,以便修复编译器或文档。
因此我怀疑,每次导入
mypackage时,它并不会从a_test.go导入整个被导入的包。
写这个只是为了确认@NobbZ所说的。
任何以_test结尾的文件在构建时都会被忽略。
❯ cat a.go
package main
func main() {
printSomething()
}
❯ cat a_test.go
package main
import "fmt"
func printSomething() {
fmt.Println("something")
}
尝试编译… 正确地无法从main()调用printSomething,因为它是_test文件的一部分。
❯ go build .
# _/tmp/glb
./a.go:4:3: undefined: printSomething
只需将a_test.go重命名为ab.go,它就能正常编译——不会抛出任何错误。
❯ mv a_test.go ab.go ❯ go build . ❯
当你做什么时没有编译错误?
如果我复制你的文件并尝试编译它们,会失败:
$ go build .
# _/tmp/tmp.Z4s5MMdPvS
./a.go:4:4: undefined: printSomething
为了完整性和可比性:
$ go version
go version go1.14.6 linux/amd64
这种行为在 Go 1.12 到 1.15 版本中是可复现的:
$ for i in 12 13 14; do nix run nixos.go_1_$i -c go version; nix run nixos.go_1_$i -c go build .; done
go version go1.12.17 linux/amd64
# _/tmp/tmp.Z4s5MMdPvS
./a.go:4:4: undefined: printSomething
go version go1.13.12 linux/amd64
# _/tmp/tmp.Z4s5MMdPvS
./a.go:4:4: undefined: printSomething
go version go1.14.4 linux/amd64
# _/tmp/tmp.Z4s5MMdPvS
./a.go:4:4: undefined: printSomething
$ nix run nixpkgs.go_1_15 -c go version; nix run nixpkgs.go_1_15 -c go build .
go version go1.15beta1 linux/amd64
# _/tmp/tmp.Z4s5MMdPvS
./a.go:4:4: undefined: printSomething


