1.go test之測試函數


在包目錄內,所有以_test.go為后綴名的源文件在執行go build時不會被構建成包的一部分,它們是go test測試的一部分。

*_test.go文件中,有三種類型的函數:測試函數、基准測試(benchmark)函數、示例函數一個測試函數是以Test為函數名前綴的函數,用於測試程序的一些邏輯行為是否正確;go test命令會調用這些測試函數並報告測試結果是PASS或FAIL。基准測試函數是以Benchmark為函數名前綴的函數,它們用於衡量一些函數的性能;go test命令會多次運行基准函數以計算一個平均的執行時間。示例函數是以Example為函數名前綴的函數,提供一個由編譯器保證正確性的示例文檔。

本節主要簡單介紹一下測試函數,以及go test的一些常用命令。

現在的目錄結構如下:在word包下,含有兩個文件,一個是word.go,該文件內有一個判斷字符串是否是回文串的函數。另一個是測試文件word_test.go。

D:\workspace\GoRepo\gopl\ch11\word>ls
word.go word_test.go

 

word.go文件

package word

import "unicode"

func IsPalindrome(s string) bool {
    // 處理非ASCII字符,比如中文
    var letters []rune
    for _, r := range s {
        if unicode.IsLetter(r) {
            letters = append(letters, unicode.ToLower(r))
        }
    }

    length := len(letters)
    for i := 0; i < length/2; i++ {
        if letters[i] != letters[length-i-1] {
            return false
        }
    }
    return true
}

 

一個簡單的測試函數可以寫成如下,每個測試函數必須導入testing包。測試函數有如下的簽名:

func TestName(t *testing.T) {
    // ...
}

 

特別注意,測試函數的名字必須以Test開頭,可選的后綴名必須以大寫字母開頭,比如

func TestFoo(t *testing.T) { // 正確
  // ... 
}

func Testfoo(t *testing.T) { // 錯誤
  // ... 
}

 

一個簡單的測試文件可以寫成這樣:

package word

import "testing"

func TestIsPalindrome(t *testing.T) {
    if !IsPalindrome("detartrated") {
        t.Error(`IsPalindrome("detartrated") = false`)
    }
    if !IsPalindrome("kayak") {
        t.Error(`IsPalindrome("kayak") = false`)
    }
}

func TestNonPalindrome(t *testing.T)  {
   if IsPalindrome("abcd") {
      t.Error(`IsPalindrome("abcd") = true`)
   }
}

go test 命令如果沒有參數指定具體哪個包,那么將默認采用當前目錄對應的包(和go build命令一樣)。我們可以用下面的命令構建和運行測試。

D:\workspace\GoRepo\gopl\ch11\word1>go test
PASS
ok      _/D_/workspace/GoRepo/gopl/ch11/word1   0.955s

如果顯示PASS,說明所有測試用例均已經通過。

 

參數-v可用於打印每個測試函數的名字和運行時間:

D:\workspace\GoRepo\gopl\ch11\word1>go test -v
=== RUN   TestIsPalindrome
--- PASS: TestIsPalindrome (0.00s)
=== RUN   TestNonPalindrome
--- PASS: TestNonPalindrome (0.00s)
PASS
ok      _/D_/workspace/GoRepo/gopl/ch11/word1   1.963s

 

參數-run對應一個正則表達式,只有測試函數名被它正確匹配的測試函數才會被go test測試命令運行:

D:\workspace\GoRepo\gopl\ch11\word1>go test -v -run="Non"
=== RUN   TestNonPalindrome
--- PASS: TestNonPalindrome (0.00s)
PASS
ok      _/D_/workspace/GoRepo/gopl/ch11/word1   0.870s

 

此外,還有-race參數也比較常用,用於檢測是否存在數據競爭非常有用,這個點在用到的時候再講。

 

最后,在寫測試文件的時候,推薦將所有測試數據合並到一個測試的表格中。比如,寫成下面這樣子。這種表格驅動的測試在Go語言中很常見。我們可以很容易地向表格添加新的測試數據,並且后面的測試邏輯也沒有冗余,這樣我們可以有更多的精力去完善錯誤信息。

func TestAllCases(t *testing.T) {
    // 把所有測試用例裝在一個結構體數組中
    var tests = []struct {
        input string
        want bool
    } {
        {"",true},
        {"a",true},
        {"aa",true},
        {"abba",true},
        {"ab",false},
        {"A man, a plan, a canal: Panama",true},
        {"哈哈哈",true},
    }

    for _, test := range tests {
        // 如果返回結果不和預期的一致,則測試不通過
        if res := IsPalindrome(test.input); res != test.want {
            t.Errorf("IsPalindrome(%q) = %v", test.input, res)
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM