mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2024-11-24 23:29:01 +00:00
50 lines
2.5 KiB
Markdown
50 lines
2.5 KiB
Markdown
### 11.2.1. 隨機測試
|
||
|
||
表格驅動的測試便於構造基於精心挑選的測試數據的測試用例。另一種測試思路是隨機測試,也就是通過構造更廣泛的隨機輸入來測試探索函數的行爲。
|
||
|
||
那麽對於一個隨機的輸入,我們如何能知道希望的輸出結果呢?這里有兩種處理策略。第一個是編寫另一個對照函數,使用簡單和清晰的算法,雖然效率較低但是行爲和要測試的函數是一致的,然後針對相同的隨機輸入檢査兩者的輸出結果。第二種是生成的隨機輸入的數據遵循特定的模式,這樣我們就可以知道期望的輸出的模式。
|
||
|
||
下面的例子使用的是第二種方法:randomPalindrome函數用於隨機生成迴文字符串。
|
||
|
||
```Go
|
||
import "math/rand"
|
||
|
||
// randomPalindrome returns a palindrome whose length and contents
|
||
// are derived from the pseudo-random number generator rng.
|
||
func randomPalindrome(rng *rand.Rand) string {
|
||
n := rng.Intn(25) // random length up to 24
|
||
runes := make([]rune, n)
|
||
for i := 0; i < (n+1)/2; i++ {
|
||
r := rune(rng.Intn(0x1000)) // random rune up to '\u0999'
|
||
runes[i] = r
|
||
runes[n-1-i] = r
|
||
}
|
||
return string(runes)
|
||
}
|
||
|
||
func TestRandomPalindromes(t *testing.T) {
|
||
// Initialize a pseudo-random number generator.
|
||
seed := time.Now().UTC().UnixNano()
|
||
t.Logf("Random seed: %d", seed)
|
||
rng := rand.New(rand.NewSource(seed))
|
||
|
||
for i := 0; i < 1000; i++ {
|
||
p := randomPalindrome(rng)
|
||
if !IsPalindrome(p) {
|
||
t.Errorf("IsPalindrome(%q) = false", p)
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
雖然隨機測試會有不確定因素,但是它也是至關重要的,我們可以從失敗測試的日誌獲取足夠的信息。在我們的例子中,輸入IsPalindrome的p參數將告訴我們眞實的數據,但是對於函數將接受更複雜的輸入,不需要保存所有的輸入,隻要日誌中簡單地記録隨機數種子卽可(像上面的方式)。有了這些隨機數初始化種子,我們可以很容易脩改測試代碼以重現失敗的隨機測試。
|
||
|
||
通過使用當前時間作爲隨機種子,在整個過程中的每次運行測試命令時都將探索新的隨機數據。如果你使用的是定期運行的自動化測試集成繫統,隨機測試將特别有價值。
|
||
|
||
**練習 11.3:** TestRandomPalindromes測試函數隻測試了迴文字符串。編寫新的隨機測試生成器,用於測試隨機生成的非迴文字符串。
|
||
|
||
**練習 11.4:** 脩改randomPalindrome函數,以探索IsPalindrome是否對標點和空格做了正確處理。
|
||
|
||
|
||
|