测试类型:

单元测试:

规则:
1.所有测试文件以_test.go结尾
 2.func Testxxx(*testing.T)
 3.初始化逻辑放到TestMain中
运行:
go test [flags][packages]
Go语言中的测试依赖go test命令。
 go test命令是一个按照一定约定和组织的测试代码的驱动程序。在包目录内,所有以_test.go为后缀名的源代码文件都是go test测试的一部分,不会被go build编译到最终的可执行文件中
 测试函数:
 每个测试函数必须导入testing包,测试函数名必须以Test开头,测试函数的基本格式(签名)如下:
 
覆盖率:
显示代码覆盖率的命令
go test [flags][packages] --cover
1.一般覆盖率:50%~60%,较高覆盖率80%+
 2.测试分支相互独立、全面覆盖
 3.测试单元粒度足够小,函数单一职责
依赖:

Mock
1.快速mock函数:
 为一个函数打桩
 为一个方法打桩
monkey打桩实例:
 
代码实例:
package split_string
import (
	"strings"
)
//切割字符串
//example:
//abc,b=>[a c]
func Split(str string, sep string) []string {
	var ret=make([]string,0,strings.Count(str,sep)+1)//预先分配好内存
	index := strings.Index(str, sep)
	for index >= 0 {
		ret = append(ret, str[:index])
		str = str[index+len(sep):]
		index = strings.Index(str, sep)
	}
	if str != "" {
		ret = append(ret, str)
	}
	return ret
}
package split_string
import (
	"reflect"
	"testing"
)
func TestSplit(t *testing.T) {
	ret := Split("babcbef", "b")
	want := []string{"", "a", "c", "ef"}
	if !reflect.DeepEqual(ret, want) {
		//测试用例失败了
		t.Errorf("want:%v but got:%v\n", want, ret)
	}
} //测试用例一
func Test2Split(t *testing.T) {
	ret := Split("a:b:c", ":")
	want := []string{"a", "b", "c"}
	if !reflect.DeepEqual(ret, want) {
		t.Fatalf("want:%v but get:%v\n", want, ret)
	}
} //测试用例二
//一次测试多个
func Test3Split(t *testing.T) {
	type testCase struct {
		str  string
		sep  string
		want []string
	}
	testGroup := []testCase{
		testCase{"babcbef", "b", []string{"", "a", "c", "ef"}},
		testCase{"a:b:c", ":", []string{"a", "b", "c"}},
		testCase{"abcdef", "bc", []string{"a", "def"}},
		testCase{"沙河有沙又有河", "有", []string{"沙河", "沙又", "河"}},
	}
	for _, test := range testGroup {
		got := Split(test.str, test.sep)
		if !reflect.DeepEqual(got, test.want) {
			t.Fatalf("want:%#v got:%#v\n", test.want, got)
		}
	}
}
//子测试
func Test4Split(t *testing.T) {
	type testCase struct {
		str  string
		sep  string
		want []string
	}
	testGroup := map[string]testCase{
		"case 1": testCase{"babcbef", "b", []string{"", "a", "c", "ef"}},
		"case 2": testCase{"a:b:c", ":", []string{"a", "b", "c"}},
		"case 3": testCase{"abcdef", "bc", []string{"a", "def"}},
		"case 4": testCase{"沙河有沙又有河", "有", []string{"沙河", "沙又", "河"}},
	}
	for name, test := range testGroup {
		t.Run(name, func(t *testing.T) {
			got := Split(test.str, test.sep)
			if !reflect.DeepEqual(got, test.want) {
				t.Fatalf("want:%#v got:%#v\n", test.want, got)
			}
		})
	}
} //会把每个map中的样例试结果都打印出来


 
 
//在split_string终端下
go test //进行测试
go test -v//查看测试细节
go test -cover//语句覆盖率
go test -cover -coverprofile=cover.out//将测试结果生成文件
go tool -cover -html=cover.out  //生成html文件来分析cover.out,绿色覆盖,红色未覆盖
//好的测试,测试函数覆盖率:100%  测试覆盖率:60%
基准测试:
func BenchmarkSplit(b *testing.B){
	for i:=0;i<b.N;i++{
		Split("a:b:c:d:e",":")
	}
}
go test -bench=Split
//goos: windows windows平台
// goarch: amd64  amd64位
// pkg: test/split_string
// cpu: Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
// BenchmarkSplit-12  12核   3869991    执行次数      307.2 ns/op 307.2ns/次
// PASS
// ok      test/split_string       1.539s
go test -benchmem //增加了查看对内存的申请情况
网络测试:
func TestHelloHandler(t *testing.T) {
	ln, err := net.Listen("tcp", "localhost:0")
	handleError(t, err)
	defer ln.Close()
	http.HandleFunc("/hello", HelloHandler)
	go http.Serve(ln, nil)
	resp, err := http.Get("http://" + ln.Addr().String() + "hello")
	handleError(t, err)
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	handleError(t, err)
	if string(body) != "hello world!" {
		t.Fatal("expected hello world,but got", string(body))
	}
}
基准测试
1.优化代码,需要对当前代码分析
 2.内置的测试框架提供了基准测试的能力
func BenchmarkSelect(b *testing.B) {
	InitServerIndex()
	b.ResetTimer() //定时器重置
	for i := 0; i < b.N; i++ {
		Select()
	}
}
func BenchmarkSelectParallel(b *testing.B) {
	InitServerIndex()
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			Select()
		}
	})
}



















