如何在测试时允许一个包访问另一个包的未导出数据?

cpc*_*len 0 testing integration-testing go

旅途中编程语言,第11.2.4节,存在的一个外部测试接入功能的一个例子fmt.isSpace()通过的声明IsSpacefmtexport_test.go文件.这似乎是完美的解决方案,所以这就是我所做的:

a/a.go:

package a

var x int

func Set(v int) {
    x = v
}
Run Code Online (Sandbox Code Playgroud)

a/a_test.go:

package a
import "testing"

func TestSet(t *testing.T) {
    Set(42)
    if x != 42 {
        t.Errorf("x == %d (expected 42)", x)
    }
}

func Get() int {
    return x
}
Run Code Online (Sandbox Code Playgroud)

(运行go testa/工作正常.)

b/b.go:

package b
import "path/to/a"

func CallSet() {
    a.Set(105)
}
Run Code Online (Sandbox Code Playgroud)

b/b_test.go

package b
import (
    "testing"
    "path/to/a"
)

func TestCallSet(t *testing.T) {
    CallSet()
    if r := a.Get(); r != 105 {
        t.Errorf("Get() == %d (expected 105)", r)
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,当我跑go test进来的时候b/,我得到:

./b_test.go:11: undefined: a.Get
Run Code Online (Sandbox Code Playgroud)

试图同时运行两组测试go test ./...并没有帮助.

在经历了一些相当大的讨论后,我发现" 只有在运行测试时才会将*_test.go文件编译到包中 "(强调我的).(因此,换句话说,我可以a.Geta_test外部测试包中访问a/,但不能从外部的任何包中访问a/.)

是否有其他方法可以允许一个包中的测试从另一个包访问其他内部数据,以进行集成测试?

icz*_*cza 6

如上所述,没有任何方法可以"授予"对未导出标识符的访问权限.

但是,对fmt包装测试的一些澄清是必要/合理的.

有2种测试:黑箱测试和白箱测试.

黑箱测试是当你把包作为一个"黑盒子",你只能通过它的出口标识符进行测试(通过其"公共API",还有什么其他的包看).在这种情况下,测试文件具有不同的包名称(例如,fmt_test在测试fmt包时).

白箱测试是当你使用封装的两个出口和未导出的标识符.要创建白盒测试,请在测试文件中指定与正在测试的包相同的包名(因此,fmtfmt包测试的情况下).

标准的lib fmt包中包含的测试打算是一个黑盒测试,但是它无法测试所有内容.因此,Go作者选择了混合版本:它们包含一个export_test.go使用相同包声明(package fmt)的单个测试文件,因此它可以访问fmt包的未导出标识符,并"导出"2个标识符以便另一个(黑盒子) )测试文件可以访问:

var IsSpace = isSpace
var Parsenum = parsenum
Run Code Online (Sandbox Code Playgroud)

作者这样做是因为他们希望尽量减少未使用的标识符的使用,因此这明确标记了未使用的标识符的使用,并且基本上充当了fmt包和包的黑盒测试之间的"桥梁" fmt.

这里需要注意的一点是,这些只会被"导出"到包的(黑盒)测试中fmt(fmt当然还有白盒测试),而不是其他包或其他包的测试.原因很简单,因为只有在运行包测试时,才会在构建包时解析和编译测试文件.

解?

未经报告的标识符适用于包本身,并且它们不是其他人的业务.这意味着没有其他包应该想要测试它们.如果需要进行测试,则必须在软件包自己的测试中完成.

如果要进行集成测试,您需要访问未导出的标识符,那么程序包必须导出暴露值(或其某些部分)的"内容",或者帮助测试而不导出敏感数据或实现细节.如果软件包API设计合理且测试彻底,则不应该(很少)需要这样做.