單元測驗
先看一個需求
在我們作業中,我們會遇到這樣的情況,就是去確認一個函式,或者一個模塊的結果是否正確.
傳統的方法
15.2.1 傳統的方式來進行測驗
在 main 函式中,呼叫 addUpper 函式,看看實際輸出的結果是否和預期的結果一致,如果一致,
則說明函式正確,否則函式有錯誤,然后修改錯誤
傳統方法的缺點分析
- 不方便, 我們需要在 main 函式中去呼叫,這樣就需要去修改 main 函式,如果現在專案正在運
行,就可能去停止專案, - 不利于管理,因為當我們測驗多個函式或者多個模塊時,都需要寫在 main 函式,不利于我們管
理和清晰我們思路 - 引出單元測驗,-> testing 測驗框架 可以很好解決問題,
單元測驗-基本介紹
Go 語言中自帶有一個輕量級的測驗框架 testing 和自帶的 go test 命令來實作單元測驗和性能測驗,
testing 框架和其他語言中的測驗框架類似,可以基于這個框架寫針對相應函式的測驗用例,也可以基
于該框架寫相應的壓力測驗用例,通過單元測驗,可以解決如下問題
- 確保 每個函式是可運行,并且運行結果是正確的
- 確保寫出來的代碼 性能是好的,
- 單元測驗能及時的發現程式設計或實作的 邏輯錯誤,使問題及早暴露,便于問題的定位解決,
而 性能測驗的重點在于發現程式設計上的一些問題,讓程式能夠在高并發的情況下還能保持穩定
單元測驗-快速入門
使用 Go 的單元測驗,對 addUpper 和 sub 函式進行測驗,
特別說明: 測驗時,可能需要暫時退出 360,(因為 360 可能會認為生成的測驗用例程式是木馬)
單元測驗快速入門總結
- 測驗用例檔案名必須以 _test.go 結尾, 比如 cal_test.go , cal 不是固定的,
- 測驗用例函式必須以 Test 開頭,一般來說就是 Test+被測驗的函式名,比如 TestAddUpper
- TestAddUpper(t *tesing.T) 的形參型別必須是 *testing.T 【看一下手冊】
- 一個測驗用例檔案中,可以有多個測驗用例函式,比如 TestAddUpper、TestSub
- 運行測驗用例指令
(1) cmd>go test [如果運行正確,無日志,錯誤時,會輸出日志]
(2) cmd>go test -v [運行正確或是錯誤,都輸出日志] - 當出現錯誤時,可以使用 t.Fatalf 來格式化輸出錯誤資訊,并退出程式
- t.Logf 方法可以輸出相應的日志
- 測驗用例函式,并沒有放在 main 函式中,也執行了,這就是測驗用例的方便之處.
- PASS 表示測驗用例運行成功,FAIL 表示測驗用例運行失敗
- 測驗單個檔案,一定要帶上被測驗的原檔案
go test -v cal_test.go cal.go - 測驗單個方法
go test -v -test.run TestAddUpper
main包中:main.go
package main
import (
_ "fmt"
)
//一個被測驗函式
func addUpper(n int) int {
res := 0
for i := 1; i <= n - 1; i++ {
res += i
}
return res
}
func addUpper2(n int) int {
res := 0
for i := 1; i <= n - 1; i++ {
res += i
}
return res
}
func main() {
//傳統的測驗方法,就是在main函式中使用看看結果是否正確
// res := addUpper(10) // 1.+ 10 = 55
// if res != 55 {
// fmt.Printf("addUpper錯誤 回傳值=%v 期望值=%v\n", res, 55)
// } else {
// fmt.Printf("addUpper正確 回傳值=%v 期望值=%v\n", res, 55)
// }
}
text包中:cal_test.go
package cal
import (
"fmt"
"testing" //引入go 的testing框架包
)
//撰寫要給測驗用例,去測驗addUpper是否正確
func TestAddUpper(t *testing.T) {
//呼叫
res := addUpper(10)
if res != 55 {
//fmt.Printf("AddUpper(10) 執行錯誤,期望值=%v 實際值=%v\n", 55, res)
t.Fatalf("AddUpper(10) 執行錯誤,期望值=%v 實際值=%v\n", 55, res)
}
//如果正確,輸出日志
t.Logf("AddUpper(10) 執行正確...")
}
func TestHello(t *testing.T) {
fmt.Println("TestHello被呼叫..")
}
text包中:sub_test.go
package cal
import (
_ "fmt"
"testing" //引入go 的testing框架包
)
//撰寫要給測驗用例,去測驗addUpper是否正確
func TestGetSub(t *testing.T) {
//呼叫
res := getSub(10, 3)
if res != 7 {
//fmt.Printf("AddUpper(10) 執行錯誤,期望值=%v 實際值=%v\n", 55, res)
t.Fatalf("getSub(10, 3) 執行錯誤,期望值=%v 實際值=%v\n", 7, res)
}
//如果正確,輸出日志
t.Logf("getSub(10, 3) 執行正確!!!!...")
}
text包中:cal.go
package cal
//一個被測驗函式
func addUpper(n int) int {
res := 0
for i := 1; i <= n - 1; i++ {
res += i
}
return res
}
//求兩個數的查
func getSub(n1 int, n2 int) int {
return n1 - n2
}
單元測驗-綜合案例
以下兩個檔案處在一個包中:
monster.go:
package monster
import (
"encoding/json"
"io/ioutil"
"fmt"
)
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 := "d:/monster.ser"
err = ioutil.WriteFile(filePath, data, 0666)
if err != nil {
fmt.Println("write file err =", err)
return false
}
return true
}
//給Monster系結方法ReStore, 可以將一個序列化的Monster,從檔案中讀取,
//并反序列化為Monster物件,檢查反序列化,名字正確
func (this *Monster) ReStore() bool {
//1. 先從檔案中,讀取序列化的字串
filePath := "d:/monster.ser"
data, err := ioutil.ReadFile(filePath)
if err != nil {
fmt.Println("ReadFile err =", err)
return false
}
//2.使用讀取到data []byte ,對反序列化
err = json.Unmarshal(data, this)
if err != nil {
fmt.Println("UnMarshal err =", err)
return false
}
return true
}
monster_test.go:
package monster
import (
"testing"
)
//測驗用例,測驗 Store 方法
func TestStore(t *testing.T) {
//先創建一個Monster 實體
monster := &Monster{
Name : "紅孩兒",
Age :10,
Skill : "吐火.",
}
res := monster.Store()
if !res {
t.Fatalf("monster.Store() 錯誤,希望為=%v 實際為=%v", true, res)
}
t.Logf("monster.Store() 測驗成功!")
}
func TestReStore(t *testing.T) {
//測驗資料是很多,測驗很多次,才確定函式,模塊..
//先創建一個 Monster 實體 , 不需要指定欄位的值
var monster = &Monster{}
res := monster.ReStore()
if !res {
t.Fatalf("monster.ReStore() 錯誤,希望為=%v 實際為=%v", true, res)
}
//進一步判斷
if monster.Name != "紅孩兒" {
t.Fatalf("monster.ReStore() 錯誤,希望為=%v 實際為=%v", "紅孩兒", monster.Name)
}
t.Logf("monster.ReStore() 測驗成功!")
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/61791.html
標籤:Go
下一篇:Go-內置time包
