第一個Go的測試


Posted by Nacho on 2020-04-05

實作目標

學習寫第一個Go的單元測試的作法與了解它的使用方式。

開始

為什麼要寫測試?

  • 確保code執行過程中的正確性
  • 確保後續維護不會出錯
  • 以防edeg case的發生

準備程式執行檔與測試檔

在動手寫測試以前得先知道測試要寫在哪裡。一般在Go的環境中,測試檔案要另外寫在一個檔案並放在同一個路徑下,且命名要是程式執行檔名加 _test,例如我的程式實際執行在main.go,我的測試就會寫在main_test.go裡,並執行go test來測試。

# 專案結構
myproject/
- calc.go
- calc_test.go 
- main.go
- main_test.go

測試範例

這裡簡單在main.go寫一個回傳x+2結果的函式,並印出結果。接著在同一個目錄底下新增一個main_test.go,引入Go提供的testing套件,並寫一個test case。

# main.go
package main

import "fmt"

func Calculate(x int) (result int){
    result = x + 2
    return result
}

func main() {
    fmt.Println("main start!!")
    cal := Calculate(2)
    fmt.Println("cal:", cal)
}

---

# main_test.go
package main

import "testing"

func TestCalculate(t *testing.T) {
    if Calculate(2) != 4 { // 如果結果不為4,就噴出error裡的內容
        t.Error("Expected 2 + 2 to equal 4")
    }
}

由於,Calculate(2)結果必為4,所以通過所有測試。go test會幫忙執行所有_test.go的test case,如果想要看到詳細的測試輸出(verbose Test output),例如那些功能被執行、那些通過可以執行go test -v

nacho@ubuntu:~/go/simpleTest$ go test
PASS
ok      _/home/nacho/go/simpleTest       0.003s

此外,也可以設計Table driven testing來為不同範圍的輸入輸出值來進行測試,所以測試相同的函式不需要再做重複的copy&past,此外,設計多組測試也能降低Edge case跟bug在程式實際上線後才發現的情況。

# main_test.go

...

func TestTableCalculate(t * testing.T){
    var tests = []struct {
        input int
        expected int
    }{
        {2, 4},
        {-1, 1},
        {0, 2},
        {-5, -3},
        {9999, 10001},
    }   

    for _, test := range tests {
        if output := Calculate(test.input); output != test.expected {
            t.Error("Test Failed: input {}, expect {}, should receive: {}", test.input, test.expected, output)
        }
    }

}

詳細的測試輸出結果。

nacho@ubuntu:~/go/simpleTest$ go test -v
=== RUN   TestCalculate
--- PASS: TestCalculate (0.00s)
=== RUN   TestTableCalculate
--- PASS: TestTableCalculate (0.00s)
PASS
ok      _/home/nacho/go/simpleTest       0.008s

Go還提供另一個方便的參數-cover,讓開發者能評估測試的覆蓋率(coverage)。覆蓋率是一個參考,但高覆蓋率也代表這支程式完全freebug或功能完全運作正常。不需要為所有的功能撰寫詳盡的測試,以追求高覆蓋率,而要將重點放在於重要/核心的business logic上,並確保能cover到更多可能的Edge cases發生才能發揮測試做大的價值。

nacho@ubuntu:~/go/simpleTest$ go test -cover
PASS
coverage: 40.0% of statements
ok      _/home/nacho/go/simpleTest       0.003s

參考

https://tutorialedge.net/golang/intro-testing-in-go/


#Go testing







Related Posts

12. Flyweight

12. Flyweight

如何用 TensorFlow object detection API 的 Single Shot MultiBox Detector 來做 hand detection

如何用 TensorFlow object detection API 的 Single Shot MultiBox Detector 來做 hand detection

Counting Sort 計數排序

Counting Sort 計數排序


Comments