2016-08-11 68 views
1

我有一棵结构树,我想使用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()产生这方面(而不是寻找“漏洞”,唐”实际上存在)。

我想我可以定义一个生成它使用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) 
} 

但这恐慌:所谓价值方法main.X.Generate:

恐慌使用无* X指针[恢复]

而且当我从[]*X更改为[]X,它会因堆栈溢出而死亡。

这些文档在示例中非常薄,而且我在Web搜索中几乎找不到任何内容。

这怎么办?

回答

1

望着testing/quick源代码看来,你不能在同一时间创建循环定制发电机和重用quick图书馆设施生成结构的阵列部分,因为size参数,即设计限制递归调用的次数,不能被传递回quick.Value(...)

https://golang.org/src/testing/quick/quick.go(看到周围50行)

你的情况,这导致无限树迅速“爆炸”与1..50在叶子每个级别(这是堆栈ov的原因erflow)。

如果功能quick.sizedValue()已公开,我们可以用它来完成您的任务,但不幸的是情况并非如此。

顺便说一句,因为HasChildren是一个不变量,你不能简单地使它成为一个结构方法吗?

type X struct { 
    Children []*X 
} 

func (me *X) HasChildren() bool { 
    return len(me.Children) > 0 
} 

func main() { 
    .... generate X .... 
    if x.HasChildren() { 
     ..... 
    } 
} 
+0

感谢您深入挖掘!是的,来自人造的例子的'HasChildren'肯定是一个结构方法:) – SAyotte