golang 單元測試與性能分析

在這裏簡單講一下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.會出現以下圖片所示:
image.png

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)
	}
}

命令

  1. 先使用命令 go test -bench . -cpuprofile cpu.out 輸出文件cpu.out
  2. 再運行 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 中用時較長。
image.png

這時再去優化你的代碼是不是容易了許多?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章