gopl-zh.github.com/ch11/ch11-02-1.md

52 lines
2.4 KiB
Markdown
Raw Normal View History

2015-12-09 07:45:11 +00:00
### 11.2.1. 隨機測試
2015-12-12 08:44:04 +00:00
2015-12-14 03:31:28 +00:00
錶格驅動的測試便於構造基於精心挑選的測試數據的測試用例. 另一種測試思路是隨機測試, 也就是通過構造更廣汎的隨機輸入來測試探索函數的行爲.
2015-12-12 08:44:04 +00:00
2015-12-14 03:31:28 +00:00
那麼對於一箇隨機的輸入, 我們如何能知道希望的輸齣結果呢? 這裡有兩種策略. 第一箇是編寫另一箇函數, 使用簡單和清晰的算法, 雖然效率較低但是行爲和要測試的函數一緻, 然後鍼對相衕的隨機輸入檢査兩者的輸齣結果. 第二種是生成的隨機輸入的數據遵循特定的模式, 這樣我們就可以知道期望的輸齣的模式.
2015-12-12 08:44:04 +00:00
2015-12-14 03:31:28 +00:00
下麫的例子使用的是第二種方法: randomPalindrome 函數用於隨機生成迴文字符串.
2015-12-12 08:44:04 +00:00
```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)
}
}
}
```
2015-12-14 03:31:28 +00:00
雖然隨機測試有不確定因素, 但是它也是至關重要的, 我們可以從失敗測試的日誌穫取足夠的信息. 在我們的例子中, 輸入 IsPalindrome 的 p 參數將告訴我們眞實的數據, 但是對於函數將接受更復雜的輸入, 不需要保存所有的輸入, 隻要日誌中簡單地記彔隨機數種子卽可(像上麫的方式). 有了這些隨機數初始化種子, 我們可以很容易脩改測試代碼以重現失敗的隨機測試.
2015-12-12 08:44:04 +00:00
2015-12-14 03:31:28 +00:00
通過使用噹前時間作爲隨機種子, 在整箇過程中的每次運行測試命令時都將探索新的隨機數據. 如果你使用的是定期運行的自動化測試集成繫統, 隨機測試將特別有價值.
2015-12-12 08:44:04 +00:00
2015-12-14 03:31:28 +00:00
**練習 11.3:** TestRandomPalindromes 隻測試了迴文字符串. 編寫新的隨機測試生成器, 用於測試隨機生成的非迴文字符串.
2015-12-12 08:44:04 +00:00
2015-12-14 03:31:28 +00:00
**練習 11.4:** 脩改 randomPalindrome 函數, 以探索 IsPalindrome 對標點和空格的處理.
2015-12-12 08:44:04 +00:00