開發中需要確認一個函式、模組結果是否正確
func addUpper(n int)int{
res:=0
for i := 1; i <n ; i++ {
res+=i
}
return res
}
傳統方法測試就是呼叫這個函式,看返回結果是否正確
缺點:
- 需要在main函式中呼叫,測試的時候去修改main函式,執行中的專案得停止來測試
- 不利於管理,因為當我們測試多個函式或者多個模組時,都要寫在main函式中,邏輯混亂
- 引出黨員測試,testing測試框架,可以很好解決問題
基本介紹
Go 語言中自帶有一個輕量級的測試框架 testing 和自帶的 go test 命令來實現單元測試和效能測試,testing 框架可以寫測試用例、壓力測試用例,
單元測試作用 :
- 確保每個函式是可執行,並且執行結果是正確的
- 確保寫出來的程式碼效能是好的,
- 單元測試能及時的發現程式設計或實現的邏輯錯誤,使問題及早暴露,便於問題的定位解決, 而效能測試的重點在於發現程式設計上的一些問題,讓程式能夠在高併發的情況下還能保持穩定
單元測試
cal.go
func AddUpper(n int)int{
res:=0
for i := 0; i < n; i++ {
res += i
}
return res
}
cal_test.go
//編寫測試用例,測試addUpper是否正常
func TestAddUpper(t *testing.T) {
res := AddUpper(10)
if res != 55 {
fmt.Println("AddUpper(10)執行錯誤,期望值=%v 實際值=%v", 55, res)
}
//輸出日誌
t.Logf("AddUpper(10)執行正確")
}
C:\Users\55480\go\go\learn\testcase01>go test -v
# learngo/learn/testcase01
.\cat_test.go:15:3: Println call has possible formatting directive %v
FAIL learngo/learn/testcase01 [build failed]
# learngo/learn/testcase01
.\cat_test.go:15:3: Println call has possible formatting directive %v
FAIL learngo/learn/testcase01 [build failed]
C:\Users\55480\go\go\learn\testcase01>go test -v
=== RUN TestAddUpper
AddUpper(10)執行錯誤,期望值=55 實際值=45 cat_test.go:18: AddUpper(10)執行正確
--- PASS: TestAddUpper (0.00s)
PASS
ok learngo/learn/testcase01 0.080s
testing框架,會將xxx_test.go的檔案加入,呼叫testXxx方法
總結
- 測試用例檔名必須以_test.go結尾
- 測試用例函式必須以Test開頭(Test+函式名)
- 形參必須是(T *tesing.T)
- 一個測試用例檔案中,可以有多個測試用例函式,也可與在不同檔案,只要命名統一
- 執行測試用例指令
- go test 執行正確,無日誌,錯誤會輸出錯誤日誌
- go test -v 正確錯誤都會輸出日誌
- 當出現錯誤時,可以使用 t.Fatalf 來格式化輸出錯誤資訊,並退出程式
- t.Logf 方法可以輸出相應的日誌
- 測試單個檔案,一定要帶上被測試的原檔案 :
C:\Users\55480\go\learn\testcase01>go test -v cat_test.go cal.go
- 測試單個方法 :
go test -v -test.run TestAddUpper
- 預設掃描當前資料夾內所有的測試用例
案例:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
)
type monster struct {
Name string
Age int
Skill string
}
//給monster繫結方法store,可以將一個monster變數(物件),序列化後儲存到檔案中
func (this *monster) Store()bool{
//先序列化
data,err:=json.Marshal(this)
if err!=nil{
fmt.Println("marshal err=",err)
return false
}
//儲存到檔案
filePath:="c/monster.ser"
err=ioutil.WriteFile(filePath,data,0777)
if err!=nil{
fmt.Println("write fiule err=",err)
return false
}
return true
}
func (this *monster) ReStore()bool{
//反先序列化
filePath:="d/monster.ser"
data,err:=ioutil.ReadFile(filePath)
if err!=nil{
fmt.Println("readFile ",err)
return false
}
//反序列化
err= json.Unmarshal(data,this)
if err!=nil{
fmt.Println("Unmarshal err ",err)
return false
}
return true
}
測試案例
package main
import "testing"
func TestStore(t *testing.T){
//先建立一個monster例項
monster := &monster{
Name:"擦拭",
Age:12,
Skill:"風火輪",
}
res := monster.Store()
if res{
t.Fatalf("方法錯誤,希望為%v,實際為%v",true,res)
}
t.Logf("測試成功")
}
func TestReStore(t *testing.T){
//先建立一個monster例項
var monster= &monster{}
res:=monster.ReStore()
if res{
t.Fatalf("方法錯誤,希望為%v,實際為%v",true,res)
}
if monster.Name !="擦拭" {
t.Fatalf("方法錯誤,希望為%v,實際為%v","擦拭",res)
}
t.Logf("測試成功")
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結