title: Go并发编程
categories:
- Go
tag:
- Go
- GoTest
Go之测试
一、Test文件名
××××_test.go必须是这样的格式
二、测试方法
Go常用测试框架
| 框架名称 | 特征 | 优点 | 缺点 | 备注 |
|---|---|---|---|---|
| Testing | table-driver测试 支持基准测试 | Go原生 简单易用 | 不支持mock 不支持assert | testing包文档: cngolib.com/testing.htm… |
| Testify | table-driver测试 支持mock 支持assert 兼容go test | 支持assert,功能强大易用 支持mock 兼容go test 社区活跃度高 | mock能力较弱 | 官方文档:pkg.go.dev/github.com/… |
| GoConvey | 支持assert 支持web界面 支持colorized输出 支持测试用例层级嵌套 兼容go test | 支持web界面 支持colorized输出 支持测试用例层级嵌套 | 不支持mock 社区不太活跃 | 项目地址: github.com/smartystree… 安装:go get github.com/smartystree… |
| Ginkgo | 支持基准测试 支持并发测试 兼容go test | 支持并发测试 | 手册:www.ginkgo.wiki/ 安装: go get github.com/onsi/ginkgo… |
1、单元测试
测试我们写的程序写的对不对,测试函数的标准写法(必须这样写)
测试函数模板
func Test×××(t *testing.T) {
// your Coed
}
testing.T拥有的方法
func (c *T) Error(args ...interface{})
func (c *T) Errorf(format string, args ...interface{})
func (c *T) Fail()
func (c *T) FailNow()
func (c *T) Failed() bool
func (c *T) Fatal(args ...interface{})
func (c *T) Fatalf(format string, args ...interface{})
func (c *T) Log(args ...interface{})
func (c *T) Logf(format string, args ...interface{})
func (c *T) Name() string
func (t *T) Parallel()
func (t *T) Run(name string, f func(t *T)) bool
func (c *T) Skip(args ...interface{})
func (c *T) SkipNow()
func (c *T) Skipf(format string, args ...interface{})
func (c *T) Skipped() bool
example
func Fib(n int) int {
if n < 2 {
return n
}
return Fib(n-1) + Fib(n-2)
}
func TestFib(t *testing.T) {
x := Fib(10)
t.Log(x)
}
在我们的VsCode和Goland中可以直接点击run按钮,我们也可以选择使用命令行进行测试,
# PATH 是你要测试的文件的路径
go test %PATH%
# 当然他也有很多的参数
1. -v
go test -v %PATH%
输出在测试中的更多细节
2. -run
如果我们不想只想运行某一个函数,而不是文件中的所有的test函数,我们可以用这个参数
go test -run="functionName"
3. -c
生成二进制文件
go test -v -run="functionName" -c
2、压力测试(基准测试)
基准测试就是在一定的工作负载之下检测程序性能的一种方法。基准测试的基本格式如下:
测试函数模板
func Benchmark×××(b *testing.B) {
// your Code
}
testing.B拥有的方法
func (c *B) Error(args ...interface{})
func (c *B) Errorf(format string, args ...interface{})
func (c *B) Fail()
func (c *B) FailNow()
func (c *B) Failed() bool
func (c *B) Fatal(args ...interface{})
func (c *B) Fatalf(format string, args ...interface{})
func (c *B) Log(args ...interface{})
func (c *B) Logf(format string, args ...interface{})
func (c *B) Name() string
func (b *B) ReportAllocs()
func (b *B) ResetTimer()
func (b *B) Run(name string, f func(b *B)) bool
func (b *B) RunParallel(body func(*PB))
func (b *B) SetBytes(n int64)
func (b *B) SetParallelism(p int)
func (c *B) Skip(args ...interface{})
func (c *B) SkipNow()
func (c *B) Skipf(format string, args ...interface{})
func (c *B) Skipped() bool
func (b *B) StartTimer()
func (b *B) StopTimer()
example
func NoPreAlloc(n int) {
data := make([]int, 0)
for i := 0; i < n; i ++ {
data = append(data, i)
}
}
func PreAlloc(n int) {
data := make([]int, 0, n)
for i := 0; i < n; i ++ {
data = append(data, i)
}
}
func BenchmarkPreAlloc(b *testing.B) {
PreAlloc(b.N)
}
func BenchmarkNoPreAlloc(b *testing.B) {
NoPreAlloc(b.N)
}
我们为split包中的Split函数编写基准测试如下:
func BenchmarkSplit(b *testing.B) {
for i := 0; i < b.N; i++ {
Split("沙河有沙又有河", "沙")
}
}
基准测试并不会默认执行,需要增加-bench参数,所以我们通过执行go test -bench=Split命令执行基准测试,输出结果如下:
split $ go test -bench=Split
goos: darwin
goarch: amd64
pkg: github.com/Q1mi/studygo/code_demo/test_demo/split
BenchmarkSplit-8 10000000 203 ns/op
PASS
ok github.com/Q1mi/studygo/code_demo/test_demo/split 2.255s
其中BenchmarkSplit-8表示对Split函数进行基准测试,数字8表示GOMAXPROCS的值,这个对于并发基准测试很重要。10000000和203ns/op表示每次调用Split函数耗时203ns,这个结果是10000000次调用的平均值。
我们还可以为基准测试添加-benchmem参数,来获得内存分配的统计数据。
split $ go test -bench=Split -benchmem
goos: darwin
goarch: amd64
pkg: github.com/Q1mi/studygo/code_demo/test_demo/split
BenchmarkSplit-8 10000000 215 ns/op 112 B/op 3 allocs/op
PASS
ok github.com/Q1mi/studygo/code_demo/test_demo/split 2.394s
其中,112 B/op表示每次操作内存分配了112字节,3 allocs/op则表示每次操作进行了3次内存分配。