2016-08-11 65 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