一,Go testing 库 testing.T 和 testing.B 简介
testing.T
判定失败接口
Fail 失败继续
FailNow 失败终止
打印信息接口
Log 数据流 (cout 类似)
Logf format (printf 类似)
SkipNow 跳过当前测试
Skiped 检测是否跳过
综合接口产生:
Error / Errorf 报告出错继续 [ Log / Logf + Fail ]
Fatel / Fatelf 报告出错终止 [ Log / Logf + FailNow ]
Skip / Skipf 报告并跳过 [ Log / Logf + SkipNow ]
testing.B
首先 , testing.B 拥有testing.T 的全部接口。
SetBytes( i uint64) 统计内存消耗, 如果你需要的话。
SetParallelism(p int) 制定并行数目。
StartTimer / StopTimer / ResertTimer 操作计时器
testing.PB
Next() 接口 。 判断是否继续循环
二,基准测试——通过基准测试来检查性能
文件名
*_b_test.go也可以和*_test.go同文件
函数名
必须以Benchmark开头,如BenchmarkX..或Benchmark_xxx
函数参数
必须是指向testing.B的指针:b *testing.B
注:
指向testing.B类型的指针很重要。
这个指针提供的机制可以报告每个测试的输出和状态。
测试的输出格式没有标准要求
测试函数中打印信息,b.Log(),b.Logf()
测试所有go文件:go test -bench=".*"或go test -bench=".*" . 或go test -bench=.
测试指定go文件:go test -bench=".*" hash_b_test.go hash.go
go test -bench=. -benchtime=3s -benchmem
选项:
-benchtime=3s 指定运行时间
-benchmem 打印出,分配内存数次和分配的总内存
基准测试结果分析:
go test -bench=".*" convert_test.go convert.go
goos: darwin
goarch: amd64
BenchmarkMd5-8 5000000 244 ns/op 48 B/op 3 allocs/op
PASS
ok command-line-arguments 1.493s
备注:
goos 操作系统
goarch 平台
-4 表示4个CPU线程执行;
5000000 表示总共执行了500万次;
244 ns/op 表示每次执行耗时244纳秒;
48 B/op 表示每次执行分配了48字节内存;
3 allocs/op 表示每次执行分配了3次对象
提示:
go test 会测试正个包
go test hash_test.go
当测试单独一个文件时,提示找不到引用的包时,后面加上源代码文件,如go test hash_test.go hash.go
三,单元测试
分为正向路径测试和负向路径测试
正向路径测试:
在正常执行的情况下,保证代码不产生错误的测试
负向路径测试
保证代码不仅会产生错误,而且是预期的错误
Go语言中的几种单元测试:
文件名
*_test.go
函数名
必须以Test开头,如TestX..或Test_xxx
函数参数
必须是指向testing.T的指针:t *testing.T
go test -v
选项:
-v 表示提供冗余打印信息
基础测试
func TestFormatString(t *testing.T) { //一组参数测试
n := 100.001
s := FormatString(n)
t.Log(s)
if s != "100.001" {
t.Errorf("%s", s)
}
}
表组测试
func TestMultiFormatString(t *testing.T) { //多组参数测试
list := map[string]interface{}{
"10": 10,
"100": "100",
"100.001": 100.001,
"hello": "hello",
"[1 2 3]": []int{1, 2, 3},
"true": true,
"map[name:jason]": map[string]interface{}{"name": "jason"},
}
for k, v := range list {
s := FormatString(v)
t.Log(s)
if s != k {
t.Errorf("Error: %v to %s,but %s", v, k, s)
}
}
}
四,总结
Go的单元测试,主要是测试函数的运行是否符合预期
Go的基准测试,主要是测试函数的性能
示例:
package gotest
import (
"encoding/json"
"fmt"
"reflect"
"strconv"
"testing"
)
func FormatString(iface interface{}) string {
switch val := iface.(type) {
case []byte:
return string(val)
}
v := reflect.ValueOf(iface)
switch v.Kind() {
case reflect.Invalid:
return ""
case reflect.Bool:
return strconv.FormatBool(v.Bool())
case reflect.String:
return v.String()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.FormatInt(v.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return strconv.FormatUint(v.Uint(), 10)
case reflect.Float64:
return strconv.FormatFloat(v.Float(), 'f', -1, 64)
case reflect.Float32:
return strconv.FormatFloat(v.Float(), 'f', -1, 32)
case reflect.Ptr:
b, err := json.Marshal(v.Interface())
if err != nil {
return "nil"
}
return string(b)
}
return fmt.Sprintf("%v", iface)
}
func BenchmarkFormatString(b *testing.B) {
n := 10
b.ResetTimer()
for i := 0; i < b.N; i++ {
FormatString(n)
}
}
func TestFormatString(t *testing.T) {
n := 100.001
s := FormatString(n)
t.Log(s)
if s != "100.001" {
t.Errorf("%s", s)
}
}
func TestMultiFormatString(t *testing.T) {
list := map[string]interface{}{
"10": 10,
"100": "100",
"100.001": 100.001,
"hello": "hello",
"[1 2 3]": []int{1, 2, 3},
"true": true,
"map[name:jason]": map[string]interface{}{"name": "jason"},
}
for k, v := range list {
s := FormatString(v)
t.Log(s)
if s != k {
t.Errorf("Error: %v to %s,but %s", v, k, s)
}
}
}
测试:
go test -v -bench=. formatstring_test.go -benchmem
注:如果不加-v,除非测试报错,否则没有多余的输出信息