如何在Go(golang)中测试一个未导出(私有)的函数?

huangapple go评论91阅读模式
英文:

How to test a unexported (private) function in go (golang)?

问题

我对在Go语言中为“未导出(私有)函数”创建单元测试很感兴趣。然而,由于我必须将它们变为“公共”的,所以在测试包中创建单元测试对它们来说实际上非常困难。这样做最终就失去了它们作为私有函数的意义。这些辅助函数的目的是帮助模块化,既然它们已经模块化了,那么能够为它们创建单元测试而不让它们对除了测试包以外的所有人可用,这将是很好的。因为它们不是应该被其他人访问或使用的函数,除了测试套件或实际的包本身。

有什么建议吗?在Go语言中是否可能将其导出给自己的包和另一个附加包之类的东西?

英文:

I was interested in creating unit test for "unexported (private) functions" in go. However, its basically really hard to create unit tests form them in the test package because I have to make them "public". Which in the end, defeats the whole point of them being private. The point is that these helper function help modularize and now that they are modular, it would be nice to be able to create unit tests for them without making them available to everyone except the testing package, nice they are not functions that should be accessed or used by anyone else except the testing suite or the actual package itself.

Any suggestions? Is it possible to only export to its own package and 1 additional package or something of that sort in go?

答案1

得分: 80

在包内创建一个测试文件

library_test.go

package mypkg

func TestPrivateStruct(t *testing.T){
  pf := private{ "私有字段" }
  ....
}

library.go

package mypkg

type private struct {
  privateField string
}

go test mypkg -v 将运行你的测试,包括私有结构体。

英文:

create a test file within the package

library_test.go

package mypkg

func TestPrivateStruct(t *testing.T){
  pf := private{ "Private Field" }
  ....
}

library.go

package mypkg

type private struct {
  privateField string
}

go test mypkg -v will run your Tests with your private struct

答案2

得分: 20

如果你想将pkg_test作为一个测试的包名,并且仍然测试未导出的字段,一个简单的技巧是在你的包中创建一个名为export_test.go的文件,包名为pkg,然后在其中导出你的未导出字段,例如:

文件 code.go

package pkg

func getFunc(){}

文件 export_test.go

package pkg

var GetFunc = getFunc

文件 code_test.go

package pkg_test

func TestGetFunc(t *testing.T) {
    testFunc := pkg.GetFunc

    // 在这里检查你的测试场景

}

请注意,所有这些文件都在同一个文件夹中。

这个解决方案的灵感来自这里

英文:

if you want to use pkg_test name as a package name for test and still test unexported field a simple trick could be create export_test.go file in your package with package name pkg then export your unexported field in there for example

file code.go

package pkg 

func getFunc(){}

file export_test.go

package pkg 
var GetFunc = getFunc

file code_test.go

package pkg_test
func TestGetFunc(t *testing.T) {
    testFunc:=pkg.GetFunc

	//check your test scenario here
	
}

note that all these files are in the same folder

the solution is inspired from here

答案3

得分: 9

首先,您可以通过在包名后面使用内部测试的包名(例如mypkg),并在相同的包名后面添加“_test”来使用“外部”测试的包名(例如mypkg_test),将两种类型的测试都放在同一个位置作为您的包。这两种类型的测试必须在文件名以“_test.go”结尾的文件中。

但是,单元测试的整个目的是测试您包的“外部接口”(即公共函数)。也就是说,单元测试应该始终是“白盒”测试(参见白盒测试)。这样,您可以重构代码而不会破坏测试。

当然,有时您想要检查内部一致性,这是通过“外部接口”是不可能的。对于这种情况,我发现断言非常有价值。另一种可能性是添加公共的“诊断”函数,其名称表明它们不适用于正常使用。

英文:

First, you can have both types of tests in the same location as your package by using the package name for internal tests (eg mypkg) and using the same package name with "_test" appended for "external" tests (eg mypkg_test). Both types of tests must be in files whose name ends in "_test.go".

BUT, the whole point of unit tests is to test the "external interface" (ie public functions) to your package. That is unit tests should always be "white box" tests (see White Box Testing). That way you can refactor your code and your tests won't break.

Of course, sometimes you want to check internal consistency, which is not possible through the "external interface". For that I have found assertions invaluable. Another possibility would be to add public "diagnostic" function(s) with names that indicate that they are not for normal use.

1: http://devmethodologies.blogspot.com.au/2013/11/unit-tests-white-box-testing.html "Unit Tests - White Box Testing"

答案4

得分: 1

Go 1.5开始,你可以在一个包内使用内部包来共享函数,而无需将它们暴露给外部调用者。

只需在你的包内创建一个名为internal的包,将共享函数移动到internal包内的文件中,并将它们公开为公共函数。然后,你可以像通常一样为这些函数创建测试文件,使用internal_test作为包的测试文件。

例如:

project/
└── domain/
    ├── logic.go
    ├── logic_test.go
    ├── wisdom.go
    ├── wisdom_test.go
    └── internal/
        ├── shared.go
        └── shared_test.go  

只有domain包内的代码才能看到和访问internal包内公开的函数。有关更详细的描述,请参阅提案或查看Go源代码

英文:

As of Go 1.5 you can use internal packages for shared functions within a package without having to expose them to outside callers.

Simply create a package named internal inside you package, move your shared functions into files inside the internal package and expose them as public functions. Then you can create test files for these functions as you would normally, using the internal_test for the package.

For example:

project/
└── domain/
    ├── logic.go
    ├── logic_test.go
    ├── wisdom.go
    ├── wisdom_test.go
    └── internal/
        ├── shared.go
        └── shared_test.go  

Only code within the domain package would be able to see and access the functions exposed inside the internal package. For a more in depth description, see the proposal or look at the go source code.

huangapple
  • 本文由 发表于 2014年7月8日 09:30:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/24622388.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定