Stories

Detail Return Return

《Go 單元測試從入門到覆蓋率提升》(二) - Stories Detail

 

Golang相關測試框架

  在 Go 語言裏,最常用的測試框架有:自帶的 testing 包GoConveytestify

1、Go自帶的testing包

   testing 包是官方內置的,無需額外安裝,也是大多數項目的首選。

  (1)單元測試

  • 測試文件必須以 _test.go 結尾,例如:calc_test.go

  • 測試函數必須以 Test 開頭(推薦寫成 Test+函數名,更直觀)

  • 測試函數簽名固定:func TestXxx(t *testing.T),不能有返回值

  • 測試函數內部用 t.Errorf / t.Fatal 等方法輸出錯誤

    • t.Errorf:標記測試失敗,但 繼續執行後面的測試代碼
    • t.Fatal:標記測試失敗,並 立即中止當前測試函數
# 執行當前目錄下所有 *_test.go 文件
go test -v

# 只執行指定文件中的測試
go test -v calc_test.go calc.go

# 執行指定的測試函數(-count=1 表示禁用緩存,強制重新運行)
go test -v -run TestAdd calc_test.go calc.go -count=1
  更詳細的參數請參考:Go test命令行參數

  (2)性能測試

  • 文件命名:和單測一樣,文件必須以 _test.go 結尾,這樣 go test 才能識別。

  • 函數命名:基準測試函數要以 Benchmark 開頭,且必須是導出函數,比如 BenchmarkAdd

  • 函數簽名:基準測試函數必須接收一個 *testing.B 類型的參數,不能有返回值。

  • 重置計時器b.ResetTimer() 用來清空前面初始化代碼的耗時,保證只統計真正的測試部分。

  • 循環執行:基準測試裏要用 for i := 0; i < b.N; i++ { ... },被測的代碼放在循環裏。

  • b.N 的作用:Go 框架會自動調整 b.N,讓測試至少運行 1 秒左右,這樣結果更穩定。最終輸出的是平均每次運行的耗時(比如 0.25 ns/op 表示每次 0.25 納秒)。

  在calc文件夾的calc_test.go文件中新增BenchmarkAbs和BenchmarkAdd方法。

image

   基準測試的目標就是 儘可能準確地衡量一段代碼的性能,包括運行時間、內存分配等。

  • 核心思路:同一段代碼運行很多次(b.N 次),用「總耗時 ÷ b.N」算出平均每次執行的耗時。

  • b.N 的作用b.N 由 Go 測試框架自動決定,會動態調整,保證測試至少運行 1 秒左右,避免樣本太少導致結果不準。

  • 運行過程:當執行 go test -bench=. 時,框架會先用很小的 b.N(比如 1、2、5、19)試跑幾次,估算耗時,再逐步增大 b.N,直到結果穩定。

  • 輸出示例:比如報告裏寫 1000000000 0.25 ns/op,意思是運行了 10 億次,每次平均耗時 0.25 納秒。

image

 

image

 

# 運行所有基準測試
go test -bench=.

# 運行所有基準測試並顯示內存分配情況
go test -bench=. -benchmem

# 只運行基準測試,不運行單元測試
go test -run=none -bench=.

# 指定測試時間
go test -bench=. -benchtime=3s

# 指定運行輪數
go test -bench=. -count=3

# 組合使用多種參數
go test -run=none -bench=. -benchmem -benchtime=3s -count=3

2、GoConvey

https://github.com/smartystreets/goconvey
  GoConvey 是一款專門為 Golang 打造的測試框架,它不僅能幫你更方便地組織和運行單元測試,還自帶了豐富的斷言方法,讓測試代碼更簡潔直觀。更酷的是,它還支持 Web 界面:只要在項目裏寫好測試,用 go test 命令就能照常運行;如果你想要更直觀的體驗,可以直接運行 goconvey,然後在瀏覽器裏訪問 http://localhost:8080,就能看到實時的測試結果展示。

  相比起純粹使用標準庫的 testing 包,Convey 讓單元測試的書寫和閲讀都更流暢,尤其適合需要頻繁跑測試、調試邏輯的開發過程。

  (1)安裝依賴:go get github.com/smartystreets/goconvey

  (2)demo

image

 

image

 

3、testify

  Testify 是 Go 語言生態裏非常常用的一個 斷言風格測試框架。它不僅提供了開發者最常用的斷言方法(讓測試代碼更簡潔、可讀性更強),還額外封裝了三個核心功能模塊:

  • Assertions(斷言):內置了豐富的斷言方法,避免重複編寫樣板式判斷邏輯。

  • Suite(測試套件):支持將一組相關測試組織在一起,方便共享初始化、清理等邏輯。

  • Mock(模擬):提供強大的 Mock 能力,方便在單元測試中模擬依賴對象或外部接口。

  藉助 Testify,我們可以用更接近自然語言的方式編寫測試,不僅提高開發效率,也讓測試結果更易於理解。

官方文檔:https://godoc.org/github.com/stretchr/testify

  (1)依賴安裝:go get -u -v github.com/stretchr/testify

  (2)測試用例

  ① assert包提供了斷言工具,在執行時會將case標記為失敗,但程序不會退出,而是繼續往下執行。

package testify

import (
    "testing"

    "github.com/stretchr/testify/assert"
)

func Test_assert(t *testing.T) {
    a := 2
    b := 3

    // 第一個斷言失敗(故意寫錯期望值)
    assert.Equal(t, 6, a+b, "第一個斷言:2+3應該等於5,不是6")

    // 程序繼續執行下面的斷言
    t.Log("這行代碼被執行了,説明程序沒有中斷")

    // 第二個斷言通過
    assert.Equal(t, 5, a+b, "第二個斷言:2+3應該等於5")

    // 第三個斷言也會執行
    assert.True(t, a < b, "第三個斷言:2應該小於3")

    t.Log("所有斷言都已執行完畢")
}

image

   ② require包提供與asser包相同的全局函數,與assert不同的是,require會終止當前測試。

package testify

import (
    "testing"
    "github.com/stretchr/testify/require"
)

func Test_require(t *testing.T) {
    name := "Tom"
    age := 18

    // 這個會失敗並停止測試
    require.Equal(t, "dazuo", name, "測試會在這裏停止")
    require.Equal(t, 18, age, "測試會在這裏停止")

    // 這行不會被執行
    t.Log("這行代碼不會被執行")
}

image

   ③ mock包提供了一種輕鬆編寫模擬對象的機制,可以在編寫測試代碼時替代實際對象使用模擬對象。

func Test_mock(t *testing.T) {
    // 創建模擬對象
    mockS := &mockStorage{}
    // 設置對Store方法期望的調用,參數必須匹配;返回該方法調用時的返回值
    mockS.On("Store", "name", "Tom").Return(1, nil).Once()

    result, err := mockS.Store("name", "Tom")
    assert.NoError(t, err)
    assert.Equal(t, 1, result)

    mockS.AssertExpectations(t) // 斷言所有預期的調用都發生了
}

image

   若該方法沒有被調用:

func Test_mock(t *testing.T) {
    // 創建模擬對象
    mockS := &mockStorage{}
    // 設置對Store方法期望的調用,參數必須匹配;返回該方法調用時的返回值
    mockS.On("Store", "name", "Tom").Return(1, nil).Once()

    mockS.AssertExpectations(t) // 斷言所有預期的調用都發生了
}

image

 

 

user avatar soroqer Avatar ligaai Avatar kohler21 Avatar daqianduan Avatar yuzhoustayhungry Avatar wnhyang Avatar aitibao_shichangyingxiao Avatar cbuc Avatar lyflexi Avatar shouke Avatar zbooksea Avatar aigoto Avatar
Favorites 53 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.