Mik*_*aig 3 testing go quickcheck property-testing
Go 不会在不同包的测试文件之间共享代码,因此测试接口的定义不会自动重用。在实践中我们如何解决这个问题?
testing/quick
:foo/foo.go
:
package foo
type Thing int
const (
X Thing = iota
Y
Z
)
Run Code Online (Sandbox Code Playgroud)
bar/bar.go
:
package bar
import (
"foo"
)
type Box struct {
Thing foo.Thing
}
Run Code Online (Sandbox Code Playgroud)
我们想要测试属性foo
,所以我们testing/quick.Generate
定义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)
}
}
Run Code Online (Sandbox Code Playgroud)
quick.Value
按预期返回Thing
[0,3) 范围内的 s:
$ 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
Run Code Online (Sandbox Code Playgroud)
让我们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)
}
}
Run Code Online (Sandbox Code Playgroud)
但Box.Generate
已经坏掉了。foo_test.go
不适用于bar_test.go
,因此quick.Value()
不使用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
Run Code Online (Sandbox Code Playgroud)
有解决方法吗?人们在实践中如何使用testing/quick
(或任何其他带有接口的测试库)?
包之间共享的任何代码都必须位于非测试文件中。但这并不意味着它必须包含在任何最终版本中;您可以使用构建约束从正常构建中排除文件,并使用构建标签在运行测试时包含它们。例如,您可以将共享测试代码放入前缀为以下内容的文件中:
//+build testtools
package mypackage
Run Code Online (Sandbox Code Playgroud)
(但未命名_test.go)。当您构建时,这不会包含在构建中。当你测试时,你会使用类似的东西:
go test -tags "testtools" ./...
Run Code Online (Sandbox Code Playgroud)
这将在构建中包含受限文件,从而使共享代码可用于测试。