单元测试是通过编写测试函数来完成的,这些函数位于_test.go文件中
要创建一个单元测试,你需要遵循以下步骤:
testing
包Test
开头,接受一个*testing.T
类型的参数testing.T
的方法如Error
, Fail
, 或 Errorf
来报告失败go test
命令,Go 测试工具会自动查找当前目录(或指定包路径)中所有以 _test.go 结尾的文件,执行其中的测试函数在运行测试命令时,如果目录包括非ASCII字符(如中文字符),那么需要显式指定源文件和测试文件
类似测试指定路径,如:
go test my/package/path
多个则用空格隔开
子测试(subtests)是一种将相关测试组织在单个测试函数中的方式。这在你想用不同参数或配置运行一组测试时非常有用。下面是一个使用子测试的例子:
func TestAdd(t *testing.T) {
// 定义一系列测试用例
testCases := []struct {
name string
a, b int // 输入参数
expected int // 期望结果
}{
{"两个正数相加", 1, 2, 3},
{"两个负数相加", -1, -2, -3},
{"正负数相加", -1, 1, 0},
}
// 遍历测试用例
for _, tc := range testCases {
// 使用t.Run()定义子测试
t.Run(tc.name, func(t *testing.T) {
result := Add(tc.a, tc.b) // 调用待测试的函数
// 断言:结果是否与期望值相符
if result != tc.expected {
t.Errorf("Add(%d, %d) 结果为 %d; 期望值为 %d", tc.a, tc.b, result, tc.expected)
}
})
}
}
在此示例中,t.Run() 用于为每个测试用例定义一个子测试。每个子测试都有一个名称和执行测试的函数。这允许你在测试输出中看到哪些子测试通过或失败。使用 go test 命令结合 -run 标志,你还可以单独运行子测试。
如果你的测试函数中有多个子测试,你可以使用 -run 标志来指定要运行的特定测试或子测试。例如,如果你只想运行名为 “两个正数相加” 的子测试,可以这样做:
go test -run TestAdd/两个正数相加
如果你需要在测试前设置一些全局状态或者在所有测试运行完后执行清理工作,可以使用TestMain
函数。这个函数应该在你的测试文件中定义,并且只能定义一次。它允许你控制测试的运行方式,包括手动调用测试函数。
TestMain函数通常接受一个*testing.M
参数,并且没有返回值。它可以调用m.Run()
来启动测试,该方法将返回一个状态码,通常会将这个状态码作为参数传递给os.Exit
来结束程序。
以下是TestMain的使用示例:
package mypackage
import (
"os"
"testing"
)
func setup() {
// 在测试运行前执行的代码
}
func teardown() {
// 在所有测试运行完后执行的代码
}
func TestMain(m *testing.M) {
setup()
// 执行测试
code := m.Run()
teardown()
// 退出程序
os.Exit(code)
}
setup函数会在任何测试运行之前执行,而teardown函数则在所有测试完成后执行。m.Run()在setup和teardown之间调用,它实际上运行所有的测试函数。然后,你可以使用它的返回值作为参数传递给os.Exit,以正确地设置程序的退出状态码。
如果你的测试文件中定义了TestMain,Go的测试运行器将调用这个函数而不是直接运行测试函数。这给了你更多的控制权,但同时也意味着你必须显式调用m.Run()来确保测试的执行
go test -run TestName
其中 TestName 是要运行的测试函数的名称。支持正则表达式,例如 -run 'TestAdd$'
只会运行 TestAdd 测试函数
go test -cover
这会输出测试的覆盖率统计信息
go test -coverprofile=coverage.out
创建一个名为 coverage.out 的文件,其中包含覆盖率数据
go tool cover -html=coverage.out
会打开一个网页,显示详细的覆盖率报告
go test -v
-v 标志将会输出每个测试函数的名称和运行结果
go test ./...
使用 ./… 运行当前目录及其所有子目录中的测试
go test -bench .
-bench
参数可以接受一个正则表达式,用来指定要运行的基准测试函数名称
go test -env "FOO=bar"
这将在测试运行时设置环境变量 FOO 的值为 bar
go test -parallel n
go test -v -coverprofile=coverage.out ./...