摘要:測試對于互聯(lián)網(wǎng)應(yīng)用軟件開發(fā)來說非常重要,它對軟件可靠性保證具有重要意義,通過測試能夠盡可能發(fā)現(xiàn)并改正軟件中的錯誤,提高軟件質(zhì)量。這里我們主要講解語言如何實(shí)現(xiàn)單元測試和性能測試。單元測試創(chuàng)建目錄,在目錄下創(chuàng)建兩個文件,為單元測試文件。
測試對于互聯(lián)網(wǎng)應(yīng)用軟件開發(fā)來說非常重要,它對軟件可靠性保證具有重要意義,通過測試能夠盡可能發(fā)現(xiàn)并改正軟件中的錯誤,提高軟件質(zhì)量。
這里我們主要講解Go語言如何實(shí)現(xiàn)單元測試和性能測試。
go語言中自帶有一個輕量級的測試框架testing和自帶的go test命令來實(shí)現(xiàn)單元測試和性能測試,testing框架和其他語言中的測試框架類似,你可以基于這個框架寫針對相應(yīng)函數(shù)的測試用例,也可以基于該框架寫相應(yīng)的壓力測試用例,那么接下來讓我們一一來看一下怎么寫。
單元測試
創(chuàng)建目錄test,在目錄下創(chuàng)建add.go、add_test.go兩個文件,add_test.go為單元測試文件。
add_test.go
package test import "testing" func TestAdd(t *testing.T) { sum := Add(1, 2) if sum == 3 { t.Log("the result is ok") } else { t.Fatal("the result is wrong") } } func TestAdd1(t *testing.T) { t.Error("the result is error") }
add.go
package test func Add(a, b int) int { return a + b }
然后在項(xiàng)目目錄下運(yùn)行go test -v就可以看到測試結(jié)果了
=== RUN TestAdd --- PASS: TestAdd (0.00s) add_test.go:8: the result is ok === RUN TestAdd1 --- FAIL: TestAdd1 (0.00s) add_test.go:14: the result is error FAIL exit status 1 FAIL _/D_/gopath/src/ados/test 0.419s
如果看到PASS字樣證明測試通過,F(xiàn)AIL字樣表示測試失敗。
使用testing庫的測試框架需要遵循以下幾個規(guī)則如下:
文件名必須是_test.go結(jié)尾的,這樣在執(zhí)行go test的時候才會執(zhí)行到相應(yīng)的代碼
你必須import testing這個包
所有的測試用例函數(shù)必須是Test開頭
測試用例會按照源代碼中寫的順序依次執(zhí)行
測試函數(shù)TestXxx()的參數(shù)是testing.T,我們可以使用該類型來記錄錯誤或者是測試狀態(tài)
測試格式:func TestXxx (t *testing.T),Xxx部分可以為任意的字母數(shù)字的組合,但是首字母不能是小寫字母[a-z],例如Testintdiv是錯誤的函數(shù)名。
函數(shù)中通過調(diào)用testing.T的Error, Errorf, FailNow, Fatal, FatalIf方法,說明測試不通過,調(diào)用Log方法用來記錄測試的信息。
性能測試或壓力測試
壓力測試用來檢測函數(shù)(方法)的性能,和編寫單元功能測試的方法類似,此處不再贅述,但需要注意以下幾點(diǎn):
壓力測試用例必須遵循如下格式,其中XXX可以是任意字母數(shù)字的組合,但是首字母不能是小寫字母
func BenchmarkXXX(b *testing.B) { ... }
go test不會默認(rèn)執(zhí)行壓力測試的函數(shù),如果要執(zhí)行壓力測試需要帶上參數(shù)-test.bench,語法:-test.bench="test_name_regex",例如go test -test.bench=".*"表示測試全部的壓力測試函數(shù)
在壓力測試用例中,請記得在循環(huán)體內(nèi)使用testing.B.N,以使測試可以正常的運(yùn)行
文件名也必須以_test.go結(jié)尾
在test目錄下創(chuàng)建 reflect_test.go
package test import ( "reflect" "testing" ) type Student struct { Name string Age int Class string Score int } func BenchmarkReflect_New(b *testing.B) { var s *Student sv := reflect.TypeOf(Student{}) b.ResetTimer() for i := 0; i < b.N; i++ { sn := reflect.New(sv) s, _ = sn.Interface().(*Student) } _ = s } func BenchmarkDirect_New(b *testing.B) { var s *Student b.ResetTimer() for i := 0; i < b.N; i++ { s = new(Student) } _ = s } func BenchmarkReflect_Set(b *testing.B) { var s *Student sv := reflect.TypeOf(Student{}) b.ResetTimer() for i := 0; i < b.N; i++ { sn := reflect.New(sv) s = sn.Interface().(*Student) s.Name = "Jerry" s.Age = 18 s.Class = "20005" s.Score = 100 } } func BenchmarkReflect_SetFieldByName(b *testing.B) { sv := reflect.TypeOf(Student{}) b.ResetTimer() for i := 0; i < b.N; i++ { sn := reflect.New(sv).Elem() sn.FieldByName("Name").SetString("Jerry") sn.FieldByName("Age").SetInt(18) sn.FieldByName("Class").SetString("20005") sn.FieldByName("Score").SetInt(100) } } func BenchmarkReflect_SetFieldByIndex(b *testing.B) { sv := reflect.TypeOf(Student{}) b.ResetTimer() for i := 0; i < b.N; i++ { sn := reflect.New(sv).Elem() sn.Field(0).SetString("Jerry") sn.Field(1).SetInt(18) sn.Field(2).SetString("20005") sn.Field(3).SetInt(100) } } func BenchmarkDirect_Set(b *testing.B) { var s *Student b.ResetTimer() for i := 0; i < b.N; i++ { s = new(Student) s.Name = "Jerry" s.Age = 18 s.Class = "20005" s.Score = 100 } }
在test目錄下,執(zhí)行:
go test reflect_test.go -test.bench=".*"
結(jié)果如下
goos: windows goarch: amd64 BenchmarkReflect_New-4 20000000 84.9 ns/op BenchmarkDirect_New-4 30000000 50.6 ns/op BenchmarkReflect_Set-4 20000000 89.9 ns/op BenchmarkReflect_SetFieldByName-4 3000000 552 ns/op BenchmarkReflect_SetFieldByIndex-4 10000000 132 ns/op BenchmarkDirect_Set-4 30000000 53.0 ns/op PASS ok command-line-arguments 10.982s
上面的結(jié)果顯示我們沒有執(zhí)行任何TestXXX的單元測試函數(shù),顯示的結(jié)果只執(zhí)行了壓力測試函數(shù),以第三行為例
BenchmarkReflect_New 函數(shù)執(zhí)行了20000000次,每次的執(zhí)行平均時間是84.9納秒。最后一行 command-line-arguments 10.982s,代表總的執(zhí)行時間為 10.982s。
如果只想對某個函數(shù)測試,以BenchmarkReflect_New 為例,執(zhí)行命令
go test reflect_test.go -test.bench="BenchmarkReflect_New"
結(jié)果為:
goos: windows goarch: amd64 BenchmarkReflect_New-4 20000000 84.9 ns/op PASS ok command-line-arguments 2.490s
如果測試整個目錄下的所有測試執(zhí)行:
go test -test.bench=".*"
如果想顯示內(nèi)存分配的次數(shù)和大小添加 -benchmem
go test reflect_test.go -benchmem -test.bench=".*"
goos: windows goarch: amd64 BenchmarkReflect_New-4 20000000 88.3 ns/op 48 B/op 1 allocs/op BenchmarkDirect_New-4 30000000 53.8 ns/op 48 B/op 1 allocs/op BenchmarkReflect_Set-4 20000000 90.9 ns/op 48 B/op 1 allocs/op BenchmarkReflect_SetFieldByName-4 3000000 564 ns/op 80 B/op 5 allocs/op BenchmarkReflect_SetFieldByIndex-4 10000000 135 ns/op 48 B/op 1 allocs/op BenchmarkDirect_Set-4 30000000 52.4 ns/op 48 B/op 1 allocs/op PASS ok command-line-arguments 12.955s
后兩列代表分配的內(nèi)存大小和次數(shù)(48 B/op 1 allocs/op)
推薦gotests
它是編寫Go測試的一個Golang命令行工具,可以根據(jù)目標(biāo)源文件的函數(shù)和方法簽名生成表驅(qū)動的測試。將自動導(dǎo)入測試文件中的任何新依賴項(xiàng)。
參考:
https://studygolang.com/stati...
https://www.cnblogs.com/yjf51...
links目錄
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/8916.html
摘要:單元測試簡介單元測試是語言級別提供的完整功能,測試代碼以命名,單元測試的以開頭,性能測試以開頭,運(yùn)行測試命令例子實(shí)現(xiàn)排列組合函數(shù)以及對應(yīng)的單元測試和性能測試創(chuàng)建工程目錄結(jié)構(gòu)目錄結(jié)構(gòu)說明參見規(guī)范項(xiàng)目實(shí)現(xiàn)排列組合函數(shù)實(shí)現(xiàn)單元測試和性能測 Go單元測試 簡介 單元測試是go語言級別提供的完整功能,測試代碼以*_test.go命名,單元測試的case以Test開頭,性能測試case以Bench...
摘要:最近在維護(hù)一個三年前的舊代碼,用的是框架。單元測試和語言并發(fā)控制實(shí)際上是個蛋疼的問題,夸張一點(diǎn)說,當(dāng)時的并不能特別輕松地實(shí)現(xiàn)并發(fā),甚至不能實(shí)現(xiàn)并發(fā)。語言的功能之一就是自帶單元測試。用語言之前,我的習(xí)慣是不寫單元測試。 最近在維護(hù)一個三年前的舊代碼,用的是laravel框架。 從某些方面來講,這個代碼算是比較標(biāo)準(zhǔn)為了實(shí)現(xiàn)在規(guī)定的時間內(nèi)完成相關(guān)功能,同時程序員水平不高、經(jīng)過大量優(yōu)化之后,變...
摘要:是語言編寫的用于操作文檔類庫,基于標(biāo)準(zhǔn)??梢允褂盟鼇碜x取寫入由及以上版本創(chuàng)建的文檔。年月日,社區(qū)正式發(fā)布了版本,該版本包含了很多新功能錯誤修復(fù)和性能優(yōu)化。 showImg(https://segmentfault.com/img/remote/1460000018971694?w=880&h=360); Excelize 是 Go 語言編寫的用于操作 Office Excel 文檔類庫...
摘要:持續(xù)交付持續(xù)交付豆瓣微服務(wù)離不開,而核心就是幾點(diǎn)自動化連續(xù)小范圍快速可靠。敏捷革命敏捷革命提升個人創(chuàng)造力與企業(yè)效率的全新協(xié)作模式豆瓣實(shí)際上正是敏捷開發(fā)的最佳實(shí)踐,有了前面的鋪墊,我們可以通過這本書我們來真正了解敏捷開發(fā)的全貌。 后端好書閱讀與推薦系列文章: 后端好書閱讀與推薦后端好書閱讀與推薦(續(xù))后端好書閱讀與推薦(續(xù)二)后端好書閱讀與推薦(續(xù)三)后端好書閱讀與推薦(續(xù)四)后端好書...
摘要:功能測試函數(shù)功能測試函數(shù)需要接收類型的單一參數(shù),類型用來管理測試狀態(tài)和支持格式化的測試日志。測試函數(shù)的相關(guān)說明,可以通過來查看幫助文檔。下面是一個例子被測試的進(jìn)程退出函數(shù)測試進(jìn)程退出函數(shù)的測試函數(shù)參考資料原文鏈接 原文鏈接:http://tabalt.net/blog/golang... Golang作為一門標(biāo)榜工程化的語言,提供了非常簡便、實(shí)用的編寫單元測試的能力。本文通過Golan...
閱讀 3229·2023-04-25 18:43
閱讀 910·2021-11-24 09:39
閱讀 1373·2021-10-14 09:43
閱讀 3906·2021-09-22 15:58
閱讀 1944·2019-08-29 17:18
閱讀 431·2019-08-29 14:14
閱讀 3090·2019-08-29 13:01
閱讀 1629·2019-08-29 12:33