单元测试
766字约3分钟
2025-02-04
Go语言中自带有一个轻量级的测试框架testing和自带的go test命令来实现单元测试和性能测试,testing框架和其他语言的测试框架相似,可以基于这个框架写针对相应函数的测试用例,也可以基于该框架写相应的压力测试用例。通过单元测试,可以解决:
- 确保每个函数是可运行,并且运行结果是正确的
- 确保写出来的代码性能是好的
- 单元测试能及时的发现程序设计或实现的逻辑错误,使问题暴露,便于问题的定位解决,而性能测试的重点在于发现程序设计上的一些问题,让程序能够在高并发的情况下还能保持稳定
Go 语言推荐测试文件和源代码文件放在一块,测试文件以 _test.go 结尾
- 测试用例文件名必须以_test.go结尾
- 测试用例函数必须以Test开头,一般来说就是Test+被测试的函数名
单元测试
calc.go
package main
func Add(a int, b int) int {
return a + b
}
func Mul(a int, b int) int {
return a * b
}
calc_test.go
package main
import "testing"
func TestAdd(t *testing.T) {
if ans := Add(1, 2); ans != 3 {
// 如果不符合预期,那就是测试不通过
t.Errorf("1 + 2 expected be 3, but %d got", ans)
}
if ans := Add(-10, -20); ans != -30 {
t.Errorf("-10 + -20 expected be -30, but %d got", ans)
}
}
测试的话,就在界面上点绿色的按钮就可以了
go test // 可以运行某个包下的所有测试用例
-v 参数会显示每个用例的测试结果
-run参数可以指定测试某个函数
单元测试框架提供的日志方法
子测试
如果需要给一个函数,调用不同的测试用例,可以使用子测试
子测试里面的Fatal,是不会终止程序的
package main
import (
"testing"
)
func TestAdd(t1 *testing.T) {
t1.Run("add1", func(t *testing.T) {
if ans := Add(1, 2); ans != 3 {
// 如果不符合预期,那就是测试不通过
t.Fatalf("1 + 2 expected be 3, but %d got", ans)
}
})
t1.Run("add2", func(t *testing.T) {
if ans := Add(-10, -20); ans != -30 {
t.Fatalf("-10 + -20 expected be -30, but %d got", ans)
}
})
}
TestMain函数
它是测试的入口
我们可以在TestMain里面实现测试流程的生命周期
package main
import (
"fmt"
"os"
"testing"
)
// 测试前执行
func setup() {
fmt.Println("Before all tests")
}
// 测试后执行
func teardown() {
fmt.Println("After all tests")
}
func Test1(t *testing.T) {
fmt.Println("I'm test1")
}
func Test2(t *testing.T) {
fmt.Println("I'm test2")
}
// 必须叫这个名字 测试主入口
func TestMain(m *testing.M) {
// 测试前执行
setup()
code := m.Run()
// 测试后执行
teardown()
os.Exit(code)
}
基准测试
add.go
package main
// Add 函数接受两个整数并返回它们的和
func Add(a, b int) int {
return a + b
}
add_test.go
package main
import (
"testing"
)
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
result := Add(2, 3)
if result != 5 {
b.Errorf("Add(2, 3) = %d; expected 5", result)
}
}
}
运行基准测试
go test -bench=.