我有一个结构树,我想用testing/quick
进行测试,但是将它限制在我的不变量内。
此示例代码有效:
var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
type X struct {
HasChildren bool
Children []*X
}
func TestSomething(t *testing.T) {
x, _ := quick.Value(reflect.TypeOf(X{}), rnd)
_ = x
// test some stuff here
}
但是,只要HasChildren = true
作为一个不变量,我们就会len(Children) > 0
,所以最好确保quick.Value()
生成尊重(而不是发现“错误”实际存在)。
我想我可以定义一个Generate函数,它使用quick.Value()
来填充所有变量成员:
func (X) Generate(rand *rand.Rand, size int) reflect.Value {
x := X{}
throwaway, _ := quick.Value(reflect.TypeOf([]*X{}), rand)
x.Children = throwaway.Interface().([]*X)
if len(x.Children) > 0 {
x.HasChildren = true
} else {
x.HasChildren = false
}
return reflect.ValueOf(x)
}
但这太恐慌了:
panic:使用nil * X指针调用的值方法main.X.Generate [已恢复]
当我将儿童从[]*X
更改为[]X
时,它会因堆栈溢出而死亡。
文档在示例中非常薄,我在网络搜索中几乎找不到任何内容。
如何做到这一点?
答案 0 :(得分:1)
查看testing/quick
源代码,您似乎无法创建递归自定义生成器,而同时重用quick
库工具来生成结构的数组部分,因为size
参数,旨在限制递归调用的数量,不能传递回quick.Value(...)
https://golang.org/src/testing/quick/quick.go(见第50行)
在你的情况下,这导致了一个无限的树,迅速"爆炸"在每个级别有1..50个叶子(这是堆栈溢出的原因)。
如果函数quick.sizedValue()
已公开,我们可以用它来完成你的任务,但不幸的是情况并非如此。
顺便说一下,因为HasChildren是一个不变的,你不能简单地把它变成一个struct方法吗?
type X struct {
Children []*X
}
func (me *X) HasChildren() bool {
return len(me.Children) > 0
}
func main() {
.... generate X ....
if x.HasChildren() {
.....
}
}