package testing
- testing 提供对 Go 包的自动化测试的支持。通过
go test
命令,能够自动执行如下形式的任何函数
要编写一个新的测试套件,需要创建一个名称以 _test.go 结尾的文件,该文件包含TestXxx
函数,如上所述。
将该文件放在与被测试的包相同的包中。该文件将被排除在正常的程序包之外,但在运行 “go test” 命令时将被包含。
go test 带参的常用参数有:
- -bench regexp 执行相应的 benchmarks,例如 -bench=.;
- -cover 开启测试覆盖率;
- -run regexp 只运行 regexp 匹配的函数,例如 -run=Array 那么就执行包含有 Array 开头的函数;
- -v 显示测试的详细命令。
- -benchmem: 对内存进行分析
- -memprofile:指定内存分析的结果文件为memprofile.out
- -cpuprofile:指定cpu分析的结果文件为profile.out
- -o 参数指定生成的二进制可执行程序,并执行测试,测试结束不会删除该程序。
- -cpu 参数提供一个CPU个数的列表,提供此列表后,那么测试将按照这个列表指定的CPU数设置GOMAXPROCS并分别测试。
- -count 指定每个测试执行的次数,默认执行一次。
- -timeout 测试超时退出,默认情况下,测试执行超过10分钟就会超时而退出。
命令使用
go test -v -cpuprofile cpu.out -memprofile mem.out // 测试生成内存和cpu文件
pprof生成文件分析
go tool pprof -http :8080 profile.out # 获取CPU文件分析结果
通过 http://localhost:8081/ui/ 访问网页
go tool pprof -http=":8081" memprofile.out # 分析内存
更多详细参数查看:go help testflag
类型 | 格式 | 作用 |
测试函数 | 函数名前缀为Test | 测试程序的一些逻辑行为是否正确 |
基准函数 | 函数名前缀为Benchmark | 测试函数的性能 |
示例函数 | 函数名前缀为Example | 为文档提供示例文档 |
func TestXxx(*testing.T){}
func BenchmarkXxx(*testing.B){}
func ExampleXxxx(){}
其中 Xxx 可以是任何字母数字字符串(但第一个字母不能是 [a-z]),用于识别测试例程。
Example
vim hello_test.go
package main
import "testing"
# Test
func TestHello(t *testing.T) {
got := Abs(-1)
if got != 1 {
t.Errorf("Abs(-1) = %d; want 1", got)
}
// t.Fail(): 将当前测试标识为失败,但是仍继续执行该测试。
}
# Benchmark
func BenchmarkHello(b *testing.B) {
// 基准函数会运行目标代码 b.N 次。在基准执行期间,会调整 b.N 直到基准测试函数持续足够长的时间。
for i := 0; i < b.N; i++ {
fmt.Sprintf("hello")
}
}
# Example
该包还运行并验证示例代码。示例函数可以包括以 "Output:" 开头的行注释,并在运行测试时与函数的标准输出进行比较。 (比较时会忽略前导和尾随空格。)
func ExampleHello(){
fmt.Println("hello")
// Output: hello
}
Main
测试程序有时需要在测试之前或之后进行额外的设置(setup)或拆卸(teardown)。
有时, 测试还需要控制在主线程上运行的代码。为了支持这些和其他一些情况, 如果测试文件包含函数:
func TestMain(m *testing.M)
那么生成的测试将调用 TestMain(m),而不是直接运行测试。
TestMain 运行在主 goroutine 中, 可以在调用 m.Run 前后做任何设置和拆卸。应该使用 m.Run 的返回值作为参数调用 os.Exit。
Example:
go test 如果遇到了此函数,首先调用此函数
func TestMain(m *testing.M) {
# call flag.Parse() here if TestMain uses flags
# 如果 TestMain 使用了 flags,这里应该加上 flag.Parse()
os.Exit(m.Run()) # 要继续接着执行其他测试,需要执行此语句,否则会直接执行完毕。
}
type T
T 是传递给测试函数的一种类型,它用于管理测试状态并支持格式化测试日志。测试日志会在执行测试的过程中不断累积, 并在测试完成时转储至标准输出。
当一个测试的测试函数返回时, 又或者当一个测试函数调用 FailNow 、 Fatal 、 Fatalf 、 SkipNow 、 Skip 或者 Skipf 中的任意一个时, 该测试即宣告结束。 跟 Parallel 方法一样, 以上提到的这些方法只能在运行测试函数的 goroutine 中调用。
至于其他报告方法, 比如 Log 以及 Error 的变种, 则可以在多个 goroutine 中同时进行调用。
type B
B 是传递给基准测试函数的一种类型,它用于管理基准测试的计时行为,并指示应该迭代地运行测试多少次。
一个基准测试在它的基准测试函数返回时,又或者在它的基准测试函数调用 FailNow、Fatal、Fatalf、SkipNow、Skip 或者 Skipf 中的任意一个方法时,测试即宣告结束。至于其他报告方法,比如 Log 和 Error 的变种,则可以在其他 goroutine 中同时进行调用。
跟单元测试一样,基准测试会在执行的过程中积累日志,并在测试完毕时将日志转储到标准错误。但跟单元测试不一样的是,为了避免基准测试的结果受到日志打印操作的影响,基准测试总是会把日志打印出来。