深入理解与使用go之测试–实现
引子
测试是一种重要的开发实践,用于确保代码的正确性和稳定性,通过编写全面的单元测试和集成测试,你可以增强代码的可靠性、可维护性和可扩展性,以及更好地理解代码的行为和边界条件。测试是项目生命周期的一个关键方面, 与其他一些语言相比,Go具有很强的编写测试原语。那么有以下几个问题
- go中的测试有几种
- 单元测试和集成测试是怎么区分的
- 你会区分环境(测试/生产)进行测试么
- 你的基准测试一定是正确的么
- 有哪些测试包可以提升我们的工作效率
写过代码的人都知道,我们最强大的测试方法是啥?
func add(a, b int) int {
return a + b
}
测试
func main() {
fmt.Println(add(3,4))
}
输出结果
7
得嘞您呐,齐活!本文结束
是不是一把打印
走天下,但是随着项目越来越庞大,开发人员越来越多,你负责的模块你是打印成功了,如果别人不小心改动你的依赖关系模块,别人不会再来逐一打印你的结果,那怎么办?
带着上面的这些问题,我们来讨论讨论今天要说的测试。
测试
测试的分类
老规矩,讲测试之前,我们先要搞清楚,我们go里面的测试有哪些分类
- 以
TestFuncName
命名的函数名,且文件以_test
结尾的测试- 单元测试
- 集成测试
- 数据竞争测试
- 代码覆盖测试
- 以
BenchmarkFuncName
命名的函数名,且文件以_test
结尾的测试- 基准测试
有了这些分类,我们来一个一个看
TestFuncName 测试
单元测试
单元测试是针对代码中最小的可测试单元(函数、方法、类型等)的测试。它们旨在验证单个单元的行为是否正确。单元测试通常是独立于其他代码的,并且可以快速运行
我们举上面的栗子 add_test.go
func TestAdd(t *testing.T) {
r := Add(3, 4)
if r != 7 {
t.Fail()
}
}
进入目录,执行
# go test . -v
=== RUN TestAdd
--- PASS: TestAdd (0.00s)
PASS
集成测试
比如,我们有加法,有减法,有乘法等等项目
func Add(a, b int) int {
return a + b
}
func Sub(a, b int) int {
return a - b
}
func Multi(a, b int) int {
return a * b
}
分布在三个不同的模块里,一般有两种办法
单独构建一个集成测试文件夹
├── tests │ ├── add_test.go │ ├── sub_test.go │ └── multi_test.go
进入文件夹
go test ./... -v
每个模块各自写集成测试文件
├── aa │ ├── add.go │ ├── add_test.go ├── bb │ ├── sub.go │ ├── sub_test.go ├── cc │ ├── multi.go │ ├── multi_test.go
在项目根目录下执行
go test ./... -v
这里是不是一脸懵,放单独文件夹还好理解,放各自模块那不跟单元测试混淆了么,怎么办呢,有三种方式
添加测试构建标签
我们可以在测试文件
add_test.go
的顶部添加//go:build integration
并且空一行,下一行即为正常包名//go:build integration package aa
注意:从1.17开始
//+build
就被//go:build
替代,go1.18gofmt
目前为了过渡两种都支持然后,我们在执行的时候,指定标签
go test -v -tags=integration ./...
使用环境变量
func TestOther(t *testing.T) { if os.Getenv("INTEGRATION") != "true" { t.Skip("skipping integration test") } // ... }
然后执行
export INTEGRATION=true && go test -v ./...
注意:使用环境变量测试通常可用于区分测试与生产环境的测试,比如有些资源操作,我们可以跳过生产测试
func TestInsert(t *testing.T) { if os.Getenv("ENV") == "prod" { t.Skip("ptod skipping insert test") } // ... } func TestDelete(t *testing.T) { if os.Getenv("ENV") == "prod" { t.Skip("prod skipping delete test") } // ... }
使用short模式
func TestOther(t *testing.T) { if testing.Short() { t.Skip("skipping other test") } // ... }
然后打印:
go test -v -short ./...
注意:短模式的一个重要用途就是有些执行时间很长的测试,如果我们每次测试都跑,其实是很