在這裏簡單講一下go如何寫單元測試與代碼的性能分析,代碼覆蓋率相關知識。
平時我們寫了的一些方法,想測試時一般在main包中的main函數中去調用我們寫好的函數,這樣測試不是很專業。golang自帶test工具非常好用,我們可以手動寫測試代碼,也可以在ide中使用快捷鍵先創建,我們使用下面的例子來說一下 代碼測試,性能壓測,性能分析等。
例子 demo.go
package demo
import "time"
//字符串長度
func strCount(str string) int {
var l int
l = len([]rune(str))
return l
}
//計算函數
func algorithm(a int,b int) int {
time.Sleep(time.Millisecond*100)
return a+b
}
type Demo struct {
}
// 註釋
// e.g. t.Test1(123)
func(d *Demo) Test1(v int)int{
return v+v
}
一、測試結果
我們要知道測試的函數需要傳什麼參數,應返回值是什麼參數。按需寫測試的cases。文件命名要以_test.go結尾,文件中的函數要以Test開頭。使用testing.T 下面的方法,使用這個包的相關方法即可。
demo_test.go
1. 表格數據測試
func Test_strCount(t *testing.T) {
type args struct {
str string
}
tests := []struct {
name string
args args
want int
}{
// TODO: Add test cases.
{"name1", args{"阿杜zhenxun"}, 9},
{"name2", args{"ado"}, 3},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := strCount(tt.args.str); got != tt.want {
t.Errorf("strCount() = %v, want %v", got, tt.want)
}
})
}
}
IDE中運行結果
=== RUN Test_strCount
--- PASS: Test_strCount (0.00s)
=== RUN Test_strCount/name1
--- PASS: Test_strCount/name1 (0.00s)
=== RUN Test_strCount/name2
--- PASS: Test_strCount/name2 (0.00s)
PASS
如果你不想手寫你也可以使用golang ide的開發工具直接生成此代碼。將光標放到你想測試的方法上面,mac按 command+n ,windown 應是ctrl+n.會出現以下圖片所示:
2. 簡單例子測試
// 測試例子
func ExampleDemo_Test1() {
d := Demo{}
fmt.Println(d.Test1(11))
fmt.Println(d.Test1(22))
// Output:
// 11
// 44
}
IDE中運行結果
=== RUN ExampleDemo_Test1
--- FAIL: ExampleDemo_Test1 (0.00s)
got:
22
44
want:
11
44
注: 在命名行下可以直接運行 go test 即可看到結果,其它相關命令查看 go help test
二、代碼覆蓋率
在golang的ide中運行時選 “… with Coverage” 可以顯示代碼覆蓋率
或是在命令行下執行如下2條命令在html中查看覆蓋率
go test -coverprofile=c.out
go tool cover -html=c.out
三、測試性能
性能測試我們需要將函數命名以 Benchmark開頭,使用testing.B結構體下面的方法
demo_test.go
package demo
import (
"testing"
)
func Benchmark_algorithm(b *testing.B) {
args1 := 1
args2 := 2
want := 3
b.Run("name1", func(bb *testing.B) {
for i := 0; i < 10; i++ {
if got := algorithm(args1, args2); got != want {
b.Errorf("algorithm() = %v, want %v", got, want)
}
}
})
}
運行結果
可以使用 go test -bench . -count=10 命令指定執行10次
➜ 測試 git:(master) ✗ go test -bench . -count=10
goos: darwin
goarch: amd64
pkg: go-demo/基礎知識/測試
Benchmark_algorithm/name1-8 1 1043681294 ns/op
Benchmark_algorithm/name1-8 1 1044113890 ns/op
Benchmark_algorithm/name1-8 1 1044500717 ns/op
Benchmark_algorithm/name1-8 1 1044609517 ns/op
Benchmark_algorithm/name1-8 1 1044535417 ns/op
Benchmark_algorithm/name1-8 1 1044608038 ns/op
Benchmark_algorithm/name1-8 1 1044479081 ns/op
Benchmark_algorithm/name1-8 1 1044309623 ns/op
Benchmark_algorithm/name1-8 1 1044603758 ns/op
Benchmark_algorithm/name1-8 1 1044389802 ns/op
PASS
ok go-demo/基礎知識/測試 10.456s
因爲我們在函數中休眠了0.1秒。每次測試我們調用10次此函數,執行結果發現每次1秒多一點。10次一共10秒左右。
四、生成代碼性能PDF
先對strCount寫一個性能分析代碼,使用go tool pprof 生成pdf文件
func Benchmark_strCount(b *testing.B){
s:="阿杜ado"
for i:=0;i<25;i++{
s = s+s
}
//b.Logf("len(s) = %d",len(s))
b.ResetTimer() //這裏將生成字符串的時間去除
for i:=0;i<b.N;i++{
strCount(s)
}
}
命令
- 先使用命令 go test -bench . -cpuprofile cpu.out 輸出文件cpu.out
- 再運行 go tool pprof cpu.out 安提示輸入web
注:如無法輸出,請先安裝graphviz
graphviz官方網址 http://www.graphviz.org/download
執行結果
➜ 測試 git:(master) ✗ go test -bench . -cpuprofile cpu.out
goos: darwin
goarch: amd64
pkg: go-demo/基礎知識/測試
Benchmark_strCount-8 2 705669566 ns/op
PASS
ok go-demo/基礎知識/測試 2.824s
➜ 測試 git:(master) ✗ go tool pprof cpu.out
Type: cpu
Time: Jan 31, 2020 at 2:15am (CST)
Duration: 2.77s, Total samples = 2.64s (95.28%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) pdf
Generating report in profile001.pdf
查看 profile001.pdf 發現 runtime decoderune 1.32s (50.97%),說明我們在decoderune 中用時較長。
這時再去優化你的代碼是不是容易了許多?