跳到主要内容

测试

单元测试

单元测试是指对软件的最小单位(比如函数)进行正确性的检验工作。 单元测试的步骤如下:

  1. 指定输入
  2. 调用函数得出输出
  3. 判断输出和预期输出之间的关系

复杂一些的单元测试可能还需要准备前提条件,比如创建数据库连接,执行结束后关闭数据库连接等,这些在单元测试中成为 SetUpTearDown

简单示例

  • hello.go
package gotestlearn
func Hello() string {
return "Hello World"
}
  • hello_test.go
package gotestlearn
import (
"testing"
)

func TestHello(t *testing.T) {
result := Hello() // 调用被测函数
want := "Hello World"
if result == want { // 检验预期和输出关系
t.Logf("Hello() = %v, want %v", result, want)
} else {
t.Errorf("Hello() = %v, want %v", result, want)
}
}
  • 注意事项:

    • 测试的文件最好与被测试的文件在同一个目录下,并且命名为*_test.go,比如hello_test.go
    • 单元测试函数以Test开头,名称最好和被测的函数一致,比如TestHello
    • 接收的参数为t *testing.T
  • 运行:

# 在代码文件所在的目录执行, 表示运行项目中所有的测试文件
go test -v ./...

# 查看具体的测试代码覆盖情况
go tool cover -html=cover.out -o coverage.html

go test 还支持按指定单元测试函数的名称进行测试或者使用通配符进行测试。

  • -run: 指定单元测试函数的名称
  • -v: 查看详情
  • -cpu: 指定cpu的数目,用于并发执行
  • -cover: 统计单个文件的覆盖率

性能测试

在Go语言中,性能测试函数一般以Benchmark开头,参数类型是b *testing.B。 默认情况下,go test不执行Benchmark测试,必须显示使用选项-bench

简单示例

  • hello.go
package gotestlearn
import (
"sync"
)
var mlock sync.Mutex
func Hello() int32 {
var counter int32 = 0
var wg sync.WaitGroup
for i:=0;i<10;i++ {
wg.Add(1)
go func() {
mlock.Lock()
counter++
mlock.Unlock()
wg.Done()
}()
}
wg.Wait()
return counter
}
  • hello_test.go
package gotestlearn
import (
"testing"
)

func BenchmarkHello(b *testing.B) {
// 报告内存分配
b.ReportAllocs()
for i := 0; i < b.N; i++ {
Hello()
}
}
  • 测试:
go test -bench="."

结果示例:

goos: windows
goarch: amd64
pkg: gotestlearn
cpu: AMD Ryzen 9 5900X 12-Core Processor
BenchmarkHello-24 364726 3077 ns/op 260 B/op 12 allocs/op
PASS
ok gotestlearn 1.183s
  • BenchmarkHello-24 表示主机有24核
  • 364726 表示总共执行了364726次
  • 3077 ns/op 表示每次执行平均耗时 3077 纳秒
  • 260 B/op 表示每次执行分配的内存为 260 字节
  • 12 allocs/op 表示每次执行分配了 12 次对象