<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
前言:
平時根據需求寫程式碼.人工進行測試往往不會面面俱到,還會因為需求的改變繁瑣的進行測試
通過完成一個測試函數,可以大大簡化測試的步驟,並且在需求該變的時候只需要改變一下測試的輸入與期望
Benchmark
主要測試函數的效能Example
為檔案提示範例檔案①測試函數
go test -cover
go test -cover -coverprofile=c.out
(將測試的結果存入檔案c.out)go tool cover -html=c.out
可以開啟檔案,顯示哪些程式碼沒有執行②基準測試
(1)基準測試函數需要注意的點
進行基準測試時往往是對函數的演演算法進行測驗,有時後一個演演算法在測試資料的基量不同時測試出的效果會不同我們需要對不同數量級的樣本進行測試的時候。可以自己寫一個盒子作為跳板,測試什麼數量級的資料就只進行當前數量級的測試
測試的時候命令為:go test -bench=.(將所有的跳板函數均執行一遍)或者=特定函數進行特定函數測試-benchtime=time (在被測試函數在基準函數預設的時間內執行不完時可以拿這個引數進行時間的擴充)在進行基準函數測試的時候,可能需要進行一些前置工作,如果感覺前置工作浪費時間可以使用 b.ResetTimer()對計時器進行重置
(2)基準測試程式碼
測試函數程式碼如下:
//檔名 subStr_test.go package main import ( "reflect" "testing" ) func BenchmarkSubStr(b *testing.B) { for i := 0; i < b.N; i++ { res := subStr("qwe:qw:es:wqe", ":") if !reflect.DeepEqual(res, []string{"qwe", "qw", "es", "wqe"}) { b.Errorf("不匹配") } } } func benchmarkFib(b *testing.B, n int) { for i := 0; i < b.N; i++ { Fib(n) } } func BenchmarkFib5(b *testing.B) { benchmarkFib(b, 5) } func BenchmarkFib10(b *testing.B) { benchmarkFib(b, 10) } func BenchmarkFib15(b *testing.B) { benchmarkFib(b, 15) } func BenchmarkFib20(b *testing.B) { benchmarkFib(b, 20) }
被測函數程式碼如下:
//檔名 subStr.go package main import ( "fmt" "strings" ) func subStr(str, stre string) []string { index := strings.Index(str, stre) var theSub []string for index >= 0 { // 先將分隔符前面的資料進行儲存 temp := str[:index] // 將字串往後移 str = str[index+1:] // 重新獲取下標 index = strings.Index(str, stre) if temp != "" { theSub = append(theSub, temp) } else { continue } } theSub = append(theSub, str) return theSub[:] } // 菲薄那契數列 func Fib(n int) int { if n < 2 { return n } return Fib(n-1) + Fib(n-2) } func main() { fmt.Println(subStr("q:w:ec:wer:cd:scn:cj:c:is:icc:cin:si", ":")) fmt.Printf("%#vn", subStr("q:w:ec:wer:cd:scn:cj:c:is:icc:cin:si", ":")) fmt.Println(123) }
將以上兩個檔案放在同一目錄下,執行測試命令 go test
得到測試結果:
goos: windows
goarch: amd64
cpu: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz
BenchmarkSubStr-8 1213681 1012 ns/op 352 B/op 14 allocs/op
PASS
ok _/d_/Go語言學習筆記/go語言語法部分/go語言進階語法/8.單元測試/基準測試 2.410s
測試函數如下:
package main import ( "reflect" "testing" ) type testS struct { str string ste string want []string } //進行組測試,批次進行測試,如果有哪個地方不滿足則進行異常丟擲 // func TestSubStr(t *testing.T) { // testMap := map[string]testS{ // "case_1": {"123:eqwe:123", ":", []string{"123", "eqwe", "123"}}, // "case_2": {"13:eqwe3:1@23", "3:", []string{"1", "eqwe", "1@23"}}, // "case_3": {"12@3@:@eq@we@:1@23", "@:", []string{"12@3", "@eq@we", "1@23"}}, // "case_4": {"123:eq@we:1@2@3", "q@", []string{"123:e", "we:1@2@3"}}, // "case_5": {"123:eqwe:123", "2", []string{"1", "3:eqwe:1", "3"}}, // "case_6": {"123:eqwe:123", "eqwe", []string{"123:", ":123"}}, // } // for k, v := range testMap { // res := subStr(v.str, v.ste) // if !reflect.DeepEqual(res, v.want) { // t.Errorf("%v want:%#v got:%#v", k, v.want, res) // } // } // } // 進行子測試,可以針對某個子樣本進行測試 func TestSubStr(t *testing.T) { testMap := map[string]testS{ "case_1": {"13:eqwe:123", ":", []string{"123", "eqwe", "123"}}, "case_2": {"3:eqwe3:1@23", "3:", []string{"1", "eqwe", "1@23"}}, "case_3": {"2@3@:@eq@we@:1@23", "@:", []string{"12@3", "@eq@we", "1@23"}}, "case_4": {"123:eq@we:1@2@3", "q@", []string{"123:e", "we:1@2@3"}}, "case_5": {"23:eqwe:123", "2", []string{"1", "3:eqwe:1", "3"}}, "case_6": {"123:eqwe:123", "eqwe", []string{"123:", ":123"}}, } for k, v := range testMap { t.Run(k, func(t *testing.T) { res := subStr(v.str, v.ste) if !reflect.DeepEqual(res, v.want) { t.Errorf("want:%#v got:%#v", v.want, res) } }) } }
待測函數如下:
package main import ( "fmt" "strings" ) func subStr(str, stre string) []string { index := strings.Index(str, stre) var theSub []string for index >= 0 { // 先將分隔符前面的資料進行儲存 temp := str[:index] // 將字串往後移 str = str[index+len(stre):] // 重新獲取下標 index = strings.Index(str, stre) if temp != "" { theSub = append(theSub, temp) } else { continue } } theSub = append(theSub, str) return theSub[:] } func main() { fmt.Println(subStr("q:w:ec:wer:cd:scn:cj:c:is:icc:cin:si", ":c")) fmt.Printf("%#vn", subStr("q:w:ec:wer:cd:scn:cj:c:is:icc:cin:si", ":")) fmt.Println(123) }
(1).組測試結果分析及命令:
go test
--- FAIL: TestSubStr (0.00s)
--- FAIL: TestSubStr/case_1 (0.00s)
subStr_test.go:46: want:[]string{"123", "eqwe", "123"} got:[]string{"13", "eqwe", "123"}
--- FAIL: TestSubStr/case_2 (0.00s)
subStr_test.go:46: want:[]string{"1", "eqwe", "1@23"} got:[]string{"eqwe", "1@23"}
--- FAIL: TestSubStr/case_3 (0.00s)
subStr_test.go:46: want:[]string{"12@3", "@eq@we", "1@23"} got:[]string{"2@3", "@eq@we", "1@23"}
--- FAIL: TestSubStr/case_5 (0.00s)
subStr_test.go:46: want:[]string{"1", "3:eqwe:1", "3"} got:[]string{"3:eqwe:1", "3"}
FAIL
exit status 1
FAIL _/D_/Go語言學習筆記/go語言語法部分/go語言進階語法/8.單元測試/組測試與子測試 0.155s
(2).子測試結果分析及命令:
go test -v -run=TestSubStr/case_1
(等號後面跟的是上面組測試失敗案例FAIL後面的目錄)=== RUN TestSubStr
=== RUN TestSubStr/case_1
subStr_test.go:46: want:[]string{"123", "eqwe", "123"} got:[]string{"13", "eqwe", "123"}
--- FAIL: TestSubStr (0.00s)
--- FAIL: TestSubStr/case_1 (0.00s)
FAIL
exit status 1
FAIL _/D_/Go語言學習筆記/go語言語法部分/go語言進階語法/8.單元測試/組測試與子測試 0.186s
(1)os.Args package main1 import ( "fmt" "os" ) func main() { // os.Args可以在執行函數的時候傳遞引數,但是對於-name=xxx沒有辦法將其解析 if os.Args != nil { for index, temp := range os.Args { fmt.Println("第", index+1, "個引數是:", temp) } } fmt.Println("hello") }
(2)flag.Args
package main import ( "flag" "fmt" "time" ) func main() { // 第一個引數為對應的引數,第二個引數為預設值,第三個引數為提示 // 返回的是對應型別的指標 // name := flag.String("name", "Tom", "輸入name") // sex := flag.Bool("sex", true, "是不是男性") // age := flag.Int("age", 10, "年齡") // flag.Parse() // fmt.Println(*name, *sex, *age) var name string var age int var sex bool flag.StringVar(&name, "name", "Tom", "輸入name") flag.BoolVar(&sex, "sex", true, "是不是男性") flag.IntVar(&age, "age", 10, "年齡") tim := flag.Duration("time", time.Hour, "時間") // 將輸入的資料進行解析,不使用這句話的話不能獲取到name sex age等屬性對應的值 flag.Parse() fmt.Println(name, sex, age, *tim) fmt.Println(flag.Args()) //以切片的方式返回命令列之外的其他引數 fmt.Println(flag.NArg()) //返回命令列之外的其他引數的個數 fmt.Println(flag.NFlag()) //返回使用命令列的引數的個數 }
pprof
偵錯工具進行偵錯,主要看待測模組在記憶體於時間上的效益偵錯的時候只會顯示耗費時間空間較多的程式碼段.
生成偵錯程式碼塊的檔案:go run xx.exe -cpu....
使用go語言工具檢視程式碼塊所存在的問題:go tool pprof cpu.pprof
package main import ( "flag" "fmt" "os" "runtime/pprof" "time" ) // 一段有問題的程式碼 func logicCode() { var c chan int for { select { case v := <-c: fmt.Printf("recv from chan, value:%vn", v) default: } } } func main() { var isCPUPprof bool var isMemPprof bool //獲取接收到的引數 flag.BoolVar(&isCPUPprof, "cpu", false, "turn cpu pprof on") flag.BoolVar(&isMemPprof, "mem", false, "turn mem pprof on") flag.Parse() //判斷進行什麼測試,然後執行分支,並將資訊儲存到相應的檔案內。 if isCPUPprof { file, err := os.Create("./cpu.pprof") if err != nil { fmt.Printf("create cpu pprof failed, err:%vn", err) return } pprof.StartCPUProfile(file) defer pprof.StopCPUProfile() } for i := 0; i < 8; i++ { go logicCode() } time.Sleep(20 * time.Second) if isMemPprof { file, err := os.Create("./mem.pprof") if err != nil { fmt.Printf("create mem pprof failed, err:%vn", err) return } pprof.WriteHeapProfile(file) file.Close() } }
總結:
這裡對常用的測試函數,子測試進行了詳細的講解,對於pprof引數調優僅僅做了個介紹,可以根據自己的興趣在網上找一部分pprof的例子深入學習,進行自動化測試非常方便。
到此這篇關於Go語言單元測試超詳細解析的文章就介紹到這了,更多相關Go語言單元測試內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45