go test
命令是一个按照一定的约定和组织来测试代码的程序。在包目录内,所有以_test.go
为后缀名的源文件在执行go build
时不会被构建成包的一部分,它们是go test
测试的一部分。
在*_test.go
文件中,有三种类型的函数:测试函数、基准测试(benchmark)函数、示例函数。
Test
为函数名前缀的函数,用于测试程序的一些逻辑行为是否正确;go test
命令会调用这些测试函数并报告测试结果是PASS或FAIL。Benchmark
为函数名前缀的函数,它们用于衡量一些函数的性能;go test
命令会多次运行基准测试函数以计算一个平均的执行时间。Example
为函数名前缀的函数,提供一个由编译器保证正确性的示例文档。go test
命令会遍历所有的*_test.go
文件中符合上述命名规则的函数,生成一个临时的main
包用于调用相应的测试函数,接着构建并运行、报告测试结果,最后清理测试中生成的临时文件。
cd packagexxx && go test
本地目录模式,即直接运行当前目录下的包,即 packagexxx
目录下的包的测试。
go test ./packagexxx
包列表模式,运行指定包下的测试,./packagexxx
可以指定多个(如 ./a ./b
),也可以使用 ./xxx/...
、./...
,测试该目录下的所有包,在该模式下,go test
会使用缓存,可以通过 go clean -testcache
清理缓存,或者通过手动指定 -count 1
来禁用缓存。
-run regexp
:运行正则匹配测试函数(测试的函数名须以 Test
开头,测试函数的参数须为 *testing.T
)。默认情况下,不运行任何测试。要运行所有测试,请使用 -run .
或 -run=.
。regexp
会按照不带括号的 /
分割为多个正则表达式,并且测试标识符的每个部分都必须匹配序列中的相应元素。注意,对于 -run=X/Y
这种情况,如果 X
存在 X/Y
不存在,则 X
仍会被执行,因为必须运行 X
,才能查找到到 X/Y
是否存在。
-bench regexp
:运行正则匹配基准测试(测试的函数名须以 Benchmark
开头,测试函数的参数须为 *testing.B
)。
-fuzz regexp
:模糊测试的方式,运行 Fuzz 测试,默认情况下不进行模糊测试。指定时,命令行参数必须与主模块中的一个包完全匹配,而正则表达式必须与该包中的一个模糊测试完全匹配 ,模糊测试将在常规测试、基准测试、其他模糊测试的种子语料库和 Example 完成后进行。
-list regexp
:列出所有符合正则表达式的顶层测试,不会运行任何测试。
-v
:可用于打印每个测试函数的名字和运行时间-timeout d
:超时时间,默认为 10 分钟 (10m)。-short
:告诉长时间运行的测试以缩短它们的运行时间。它默认关闭,但在 all.bash 期间设置,以便安装 Go 树可以运行健全性检查,但不能花时间运行详尽的测试 (这一句不理解,这个 all.bash?) 。-vet list
:在测试前调用 go vet
。-failfast
:在第一次测试失败后不要开始新的测试,立即失败。常见的一个测试命令:go test -v -short -failfast 2>&1 | tee log
。-json
:以 JSON 格式记录详细输出和测试结果。这提出了与机器可读格式的 -v
标志相同的信息。-parallel n
:指 t.Parallel 调用后允许产生的做到并行运行的测试数目。 在进行模糊测试时,该标志的值是可以同时调用模糊函数的最大子进程数,而不管是否调用了 t.Parallel。 默认情况下,-parallel 设置为 GOMAXPROCS 的值。 将 -parallel 设置为高于 GOMAXPROCS 的值可能会由于 CPU 争用而导致性能下降,尤其是在模糊测试时。 请注意,-parallel 仅适用于单个测试二进制文件(包)。 根据 -p 标志的设置,go test 命令也可以并行运行不同包的测试(参见 go help build)。-shuffle off,on,N
:随机测试执行顺序,默认为 off,N 为指定一个随机数种子。-run
、-bench
匹配的测试的配置-count n
,对 -fuzz
不生效。默认为 1 并在包列表模式(测试缓存)。手动指定 1 将禁用测试缓存。该参数仅用来指定测试运行的次数,如果设置了 -cpu
,则为每个 GOMAXPROCS
值运行 n 次。-cpu 1,2,4
指定运行测试的 GOMAXPROCS
列表,默认值为当前 GOMAXPROCS
值,每个测试函数会针对每一个 cpu 值运行一次。-bench
匹配的测试的配置-benchtime t
对每个基准运行足够的迭代以获取指定的 t 作为 time.Duration(例如,-benchtime 1h30s)。默认值为 1 秒 (1s)。特殊语法 Nx 表示运行准 N 次(例如,-benchtime 100x)。-benchmem
打印基准测试的内存分配统计信息。-fuzz
匹配的测试的配置-fuzztime t
和 -benchtime t
类似。-fuzzminimizetime t
和 -fuzztime t
类似,表示最小值。-cover
启用覆盖率统计-covermode set,count,atomic
设置正在测试的包的覆盖率分析模式。默认值为 set
,如果启用 -race
,默认值为 atomic
。set: bool
: 这个语句是否运行。count: int
: 这个语句运行了多少次。atomic: int: count
,但在多线程测试中是精确的;但是代价更高。-coverpkg pattern1,pattern2,pattern3
在每个测试中对匹配模式的包应用覆盖率分析。默认情况下,每个测试只分析正在测试的包。有关包模式的描述,请参阅 go help packages
。-coverprofile cover.out
在所有测试通过后,将覆盖率配置文件写入的文件。-blockprofile block.out
-blockprofilerate n
-cpuprofile cpu.out
-memprofile mem.out
-memprofilerate n
-mutexprofile mutex.out
-mutexprofilefraction n
-outputdir directory
-trace trace.out
go help build
相关标志-args
将命令行的其余部分(-args
之后的所有内容)传递给测试二进制文件,未经解释且未更改。 因为这个标志占用了命令行的剩余部分,所以包列表(如果存在)必须出现在这个标志之前。-c
将测试二进制文件编译为 pkg.test
但不要运行它(其中 pkg 是包导入路径的最后一个元素)。 可以使用 -o
标志更改文件名。(eg: go test ./01-testing -c
)-o file
将测试二进制文件编译到指定文件。测试仍然运行(除非指定了 -c 或 -i)。-exec xprog
使用 xprog
运行测试二进制文件,详见:go help run
。package word
import "unicode"
import "testing"
// IsPalindrome reports whether s reads the same forward and backward.
// Letter case is ignored, as are non-letters.
func IsPalindrome(s string) bool {
var letters []rune
for _, r := range s {
if unicode.IsLetter(r) {
letters = append(letters, unicode.ToLower(r))
}
}
for i := range letters {
if letters[i] != letters[len(letters)-1-i] {
return false
}
}
return true
}
func TestIsPalindrome(t *testing.T) {
var tests = []struct {
input string
want bool
}{
{"", true},
{"a", true},
{"aa", true},
{"ab", false},
{"kayak", true},
{"detartrated", true},
{"A man, a plan, a canal: Panama", true},
{"Evil I did dwell; lewd did I live.", true},
{"Able was I ere I saw Elba", true},
{"été", true},
{"Et se resservir, ivresse reste.", true},
{"palindrome", false}, // non-palindrome
{"desserts", false}, // semi-palindrome
}
for _, test := range tests {
if got := IsPalindrome(test.input); got != test.want {
t.Errorf("IsPalindrome(%q) = %v", test.input, got)
}
}
}
以上是一个测试回文数的测试用例,有以下内容需注意:
TestMain
。t.Errorf
时刻的堆栈调用信息。和其他编程语言或测试框架的assert断言不同,t.Errorf
调用也没有引起panic异常或停止测试的执行。