[Go Test 长路漫漫 (一) | 青训营笔记]

128 阅读2分钟
title: Go并发编程
categories: 
- Go
tag: 
- Go
- GoTest

Go之测试

一、Test文件名

××××_test.go必须是这样的格式

Test01

二、测试方法

Go常用测试框架

框架名称特征优点缺点备注
Testingtable-driver测试 支持基准测试Go原生 简单易用不支持mock 不支持asserttesting包文档: cngolib.com/testing.htm…
Testifytable-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)
 }

在我们的VsCodeGoland中可以直接点击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次内存分配。