如何在Go软件包之间共享测试接口? [英] How to share test interfaces between Go packages?
问题描述
Go不会在不同软件包的测试文件之间共享代码,因此不会自动重用测试接口的定义.在实践中我们如何解决这个问题?
Go doesn't share code between test files of different packages, so definitions of test interfaces aren't automatically reused. How can we work around this in practice?
foo/foo.go
:
package foo
type Thing int
const (
X Thing = iota
Y
Z
)
bar/bar.go
:
package bar
import (
"foo"
)
type Box struct {
Thing foo.Thing
}
我们要对 foo
进行属性测试,因此我们在 Thing
上定义 testing/quick.Generate
:
We want to property test foo
, so we define testing/quick.Generate
on Thing
:
foo_test.go
:
package foo
import (
"math/rand"
"reflect"
"testing"
"testing/quick"
"time"
)
func (_ Thing) Generate(r *rand.Rand, sz int) reflect.Value {
return reflect.ValueOf(Thing(r.Intn(3)))
}
func TestGenThing(t *testing.T) {
r := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
for i := 0; i < 5; i++ {
val, _ := quick.Value(reflect.TypeOf(Thing(0)), r)
tng, _ := val.Interface().(Thing)
t.Logf("%#v\n", tng)
}
}
quick.Value
返回预期范围在[0,3)范围内的 Thing
:
quick.Value
returns Thing
s in the range [0,3) as expected:
$ go test -v foo
=== RUN TestGenThing
--- PASS: TestGenThing (0.00s)
foo_test.go:20: 0
foo_test.go:20: 1
foo_test.go:20: 2
foo_test.go:20: 1
foo_test.go:20: 2
PASS
ok foo 0.026s
让我们的属性也测试 bar
:
package bar
import (
"math/rand"
"reflect"
"testing"
"testing/quick"
"time"
"foo"
)
func (_ Box) Generate(r *rand.Rand, sz int) reflect.Value {
val, _ := quick.Value(reflect.TypeOf(foo.Thing(0)), r)
tng, _ := val.Interface().(foo.Thing)
return reflect.ValueOf(Box{tng})
}
func TestGenBox(t *testing.T) {
r := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
for i := 0; i < 5; i++ {
val, _ := quick.Value(reflect.TypeOf(Box{}), r)
box, _ := val.Interface().(Box)
t.Logf("%#v\n", box)
}
}
但是 Box.Generate
已损坏. foo_test.go
对 bar_test.go
不可用,因此 quick.Value()
不使用 Thing.Generate()
:
But Box.Generate
is broken. foo_test.go
isn't available to bar_test.go
, so quick.Value()
doesn't use Thing.Generate()
:
$ GOPATH=$PWD go test -v bar
=== RUN TestGenBox
--- PASS: TestGenBox (0.00s)
bar_test.go:24: bar.Box{Thing:3919143124849004253}
bar_test.go:24: bar.Box{Thing:-3486832378211479055}
bar_test.go:24: bar.Box{Thing:-3056230723958856466}
bar_test.go:24: bar.Box{Thing:-847200811847403542}
bar_test.go:24: bar.Box{Thing:-2593052978030148925}
PASS
ok bar 0.095s
是否有解决方法?人们在实践中如何使用 testing/quick
(或任何其他具有接口的测试库)?
Is there a workaround for this? How do folks use testing/quick
(or any other testing library with interfaces) in practice?
推荐答案
包之间共享的任何代码都必须位于非测试文件中.但是,这并不意味着它必须包含在任何最终版本中.您可以使用构建约束将文件从常规构建中排除,然后<一个href ="https://golang.org/cmd/go/#hdr-Compile_packages_and_dependencies" rel ="nofollow noreferrer">构建标记,以便在运行测试时将其包括在内.例如,您可以将共享的测试代码放在带有以下前缀的文件中:
Any code shared between packages must be in a non-test file. That doesn't mean it has to be included in any final builds though; you can use build constraints to exclude the files from normal builds, and build tags to include them when running tests. For example, you can put your shared test code in a file prefixed with:
//+build testtools
package mypackage
(但 not 名为_test.go).构建时,它不会包含在构建中.测试时,您将使用类似以下内容的
(but not named _test.go). When you build, this will not be included in the build. When you test, you'd use something like:
go test -tags "testtools" ./...
这将在构建中包含受约束的文件,从而使共享代码可用于测试.
This would include the constrained file in the build, and thereby make the shared code available to the tests.
这篇关于如何在Go软件包之间共享测试接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!