文档¶
呈现于 Linux/AMD64 视窗/AMD 64 达尔文/AMD 64 JS/WASM
概述¶
包测试支持 Go 包的自动测试。 它旨在与“go test”命令一起使用,该命令可自动执行 执行表单的任何函数
func TestXxx(*testing.T)
其中 Xxx 不以小写字母开头。函数名称 用于识别测试例程。
在这些函数中,使用错误、失败或相关方法来发出故障信号。
若要编写新的测试套件,请创建一个文件 包含此处所述的 TestXxx 函数, 并为该文件指定一个以“_test.go”结尾的名称。 该文件将从常规文件中排除 包构建,但在运行“go test”命令时将包含在内。
测试文件可以与被测试文件位于同一包中, 或在带有后缀“_test”的相应包中。
如果测试文件在同一个包中,则可能引用未导出 包中的标识符,如以下示例所示:
package abs
import "testing"
func TestAbs(t *testing.T) {
got := Abs(-1)
if got != 1 {
t.Errorf("Abs(-1) = %d; want 1", got)
}
}
如果文件位于单独的“_test”包中,则表示正在测试的包 必须显式导入,并且只能使用其导出的标识符。 这被称为“黑匣子”测试。
package abs_test
import (
"testing"
"path_to_pkg/abs"
)
func TestAbs(t *testing.T) {
got := abs.Abs(-1)
if got != 1 {
t.Errorf("Abs(-1) = %d; want 1", got)
}
}
有关更多详细信息,请运行“go help test”和“go help testflag”。
基准¶
表单的功能
func BenchmarkXxx(*testing.B)
被视为基准测试,并在以下情况下由“go test”命令执行 提供了其 -bench 标志。基准测试按顺序运行。
有关测试标志的说明,请参阅 golang.org/cmd/go/#hdr…。
示例基准测试函数如下所示:
func BenchmarkRandInt(b *testing.B) {
for i := 0; i < b.N; i++ {
rand.Int()
}
}
基准测试函数必须运行目标代码 b.N 次。 在基准测试执行期间,b.N 被调整,直到基准测试函数持续 足够长,可以可靠地计时。输出
BenchmarkRandInt-8 68453040 17.8 ns/op
意味着环路以每个环路 68453040.17 ns 的速度运行 8 次。
如果基准测试在运行前需要一些昂贵的设置,计时器 可以重置:
func BenchmarkBigLen(b *testing.B) {
big := NewBig()
b.ResetTimer()
for i := 0; i < b.N; i++ {
big.Len()
}
}
如果基准测试需要在并行设置中测试性能,则可以使用 运行并行帮助程序函数;此类基准旨在与 Go 测试 -CPU 标志:
func BenchmarkTemplateParallel(b *testing.B) {
templ := template.Must(template.New("test").Parse("Hello, {{.}}!"))
b.RunParallel(func(pb *testing.PB) {
var buf bytes.Buffer
for pb.Next() {
buf.Reset()
templ.Execute(&buf, "World")
}
})
}
给出了基准测试结果格式的详细规范 在 golang.org/design/1431…。
有一些标准工具可用于处理 golang.org/x/perf/cmd 的基准测试结果。 特别是,golang.org/x/perf/cmd/… 执行 统计稳健的 A/B 比较。
例子¶
该包还运行并验证示例代码。示例函数可以 包括以“输出:”开头的结束行注释,并与 运行测试时函数的标准输出。(比较 忽略前导空格和尾随空格。这些是示例的示例:
func ExampleHello() {
fmt.Println("hello")
// Output: hello
}
func ExampleSalutations() {
fmt.Println("hello, and")
fmt.Println("goodbye")
// Output:
// hello, and
// goodbye
}
注释前缀“无序输出:”类似于“输出:”,但匹配任何 行顺序:
func ExamplePerm() {
for _, value := range Perm(5) {
fmt.Println(value)
}
// Unordered output: 4
// 2
// 1
// 3
// 0
}
没有输出注释的示例函数将被编译但不执行。
用于声明包、函数 F、类型 T 和示例的命名约定 T型的方法M是:
func Example() { ... }
func ExampleF() { ... }
func ExampleT() { ... }
func ExampleT_M() { ... }
包/类型/函数/方法的多个示例函数可能由 向名称追加不同的后缀。后缀必须以 小写字母。
func Example_suffix() { ... }
func ExampleF_suffix() { ... }
func ExampleT_suffix() { ... }
func ExampleT_M_suffix() { ... }
当整个测试文件包含单个时,整个测试文件将作为示例呈现 示例函数,至少一个其他函数、类型、变量或常量 声明,并且没有测试或基准测试函数。
模糊¶
“Go Test”和测试包支持模糊测试,这是一种测试技术,其中 使用随机生成的输入调用函数以查找错误而不是 由单元测试预期。
表单的功能
func FuzzXxx(*testing.F)
被视为模糊测试。
例如:
func FuzzHex(f *testing.F) {
for _, seed := range [][]byte{{}, {0}, {9}, {0xa}, {0xf}, {1, 2, 3, 4}} {
f.Add(seed)
}
f.Fuzz(func(t *testing.T, in []byte) {
enc := hex.EncodeToString(in)
out, err := hex.DecodeString(enc)
if err != nil {
t.Fatalf("%v: decode: %v", in, err)
}
if !bytes.Equal(in, out) {
t.Fatalf("%v: not equal after round trip: %v", in, out)
}
})
}
模糊测试维护一个种子语料库,或一组由 默认,并且可以生成种子输入。种子输入可以通过以下方式注册 呼叫 (*F)。添加或通过将文件存储在目录中 testdata/fuzz/ (其中<名称>是模糊测试的名称)在包含以下内容的包装内 模糊测试。种子输入是可选的,但模糊测试引擎可能会发现 当提供一组具有良好 代码覆盖率。这些种子输入也可以用作错误的回归测试 通过模糊测试识别。
传递给 (*F) 的函数。模糊测试中的模糊被认为是模糊 目标。模糊目标必须接受 *T 参数,后跟一个或多个参数 随机输入的参数。传递给 (*F) 的参数类型。添加必须 与这些参数的类型相同。模糊目标可能发出信号 它发现问题的方式与测试相同:通过调用 T.Fail(或任何 方法称其为T.Error或T.Fatal)或恐慌。
启用模糊测试时(通过将 -fuzz 标志设置为正则表达式 与特定的模糊测试匹配),使用参数调用模糊目标 通过反复对种子输入进行随机更改而生成。上 支持的平台,“Go Test”使用模糊测试编译测试可执行文件 覆盖率仪器。模糊测试引擎使用该检测来 查找和缓存可扩大覆盖范围的输入,从而增加 查找错误。如果给定输入的模糊目标失败,则模糊测试引擎 将导致失败的输入写入目录中的文件 testdata/fuzz/ 在包目录中。此文件稍后用作 种子输入。如果文件无法在该位置写入(例如, 因为目录是只读的),模糊测试引擎将文件写入 而是生成缓存中的模糊缓存目录。
禁用模糊测试时,将使用种子输入调用模糊目标 注册了F.Add和来自testdata/fuzz/的种子输入。在此 模式,模糊测试的行为与常规测试非常相似,子测试已开始 用F.Fuzz而不是T.Run。
有关模糊测试的文档,请参阅 go.dev/doc/fuzz。
跳¶
可以在运行时跳过测试或基准测试,调用 跳过 *T 或 *B 的方法:
func TestTimeConsuming(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
...
}
如果输入无效,则可以在模糊目标中使用 *T 的 Skip 方法, 但不应被视为失败的输入。例如:
func FuzzJSONMarshaling(f *testing.F) {
f.Fuzz(func(t *testing.T, b []byte) {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
t.Skip()
}
if _, err := json.Marshal(v); err != nil {
t.Errorf("Marshal: %v", err)
}
})
}
子测试和子基准¶
T 和 B 的运行方法允许定义子测试和子基准, 无需为每个函数定义单独的函数。这使得可以使用 比如表驱动的基准测试和创建分层测试。 它还提供了一种共享常见设置和拆卸代码的方法:
func TestFoo(t *testing.T) {
// <setup code>
t.Run("A=1", func(t *testing.T) { ... })
t.Run("A=2", func(t *testing.T) { ... })
t.Run("B=1", func(t *testing.T) { ... })
// <tear-down code>
}
每个子测试和子基准都有一个唯一的名称:名称的组合 顶级测试和传递给 Run 的名称序列,分隔为 斜杠,带有可选的尾随序列号以消除歧义。
-run、-bench 和 -fuzz 命令行标志的参数是未锚定的常规 与测试名称匹配的表达式。对于具有多个斜杠分隔的测试 元素,例如子测试,参数本身以斜杠分隔,带有 依次匹配每个 name 元素的表达式。因为它是未锚定的,所以 空表达式匹配任何字符串。 例如,使用“匹配”表示“其名称包含”:
go test -run '' # Run all tests.
go test -run Foo # Run top-level tests matching "Foo", such as "TestFooBar".
go test -run Foo/A= # For top-level tests matching "Foo", run subtests matching "A=".
go test -run /A=1 # For all top-level tests, run subtests matching "A=1".
go test -fuzz FuzzFoo # Fuzz the target matching "FuzzFoo"
-run 参数还可用于运行种子中的特定值 语料库,用于调试。例如:
go test -run=FuzzFoo/9ddb952d9814
可以设置 -fuzz 和 -run 标志,以便模糊目标,但 跳过所有其他测试的执行。
子测试也可用于控制并行度。父测试将仅 在其所有子测试完成后完成。在此示例中,所有测试都是 彼此并行运行,并且仅彼此运行,无论 可以定义的其他顶级测试:
func TestGroupedParallel(t *testing.T) {
for _, tc := range tests {
tc := tc // capture range variable
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
...
})
}
}
在并行子测试完成之前,Run 不会返回,从而提供了一种方法 要在一组并行测试后进行清理,请执行以下操作:
func TestTeardownParallel(t *testing.T) {
// This Run will not return until the parallel tests finish.
t.Run("group", func(t *testing.T) {
t.Run("Test1", parallelTest1)
t.Run("Test2", parallelTest2)
t.Run("Test3", parallelTest3)
})
// <tear-down code>
}
主要¶
测试或基准测试程序有时需要进行额外的设置或拆卸 在执行之前或之后。有时还需要控制 哪些代码在主线程上运行。为了支持这些和其他情况, 如果测试文件包含函数:
func TestMain(m *testing.M)
然后生成的测试将调用TestMain(m),而不是运行测试或基准测试 径直。TestMain 在主 goroutine 中运行,可以执行任何设置 并且需要围绕 m.Run 的调用进行拆解。m.Run 将返回一个出口 可以传递给操作系统的代码。退出。如果 TestMain 返回,则测试包装器 会将 m.Run 的结果传递给操作系统。退出自身。
当调用 TestMain 时,标志。尚未运行解析。如果测试主要取决于 命令行标志,包括测试包的标志,它应该调用 旗。显式解析。命令行标志始终由时间测试解析 或基准测试函数运行。
TestMain 的一个简单实现是:
func TestMain(m *testing.M) {
// call flag.Parse() here if TestMain uses flags
os.Exit(m.Run())
}
TestMain 是一个低级原语,对于休闲来说应该是必需的 测试需求,其中普通测试功能就足够了。
指数¶
- func AllocsPerRun(run int, f func()) (avg float64)
- func CoverMode() 字符串
- func 覆盖率() float64
- func Init()
- func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, ...)
- 函数寄存器封面(c 封面)
- func RunBenchmarks(matchString func(pat, str string) (bool, error), ...)
- func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool)
- func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)
- func Short() bool
- func verbose() bool
- B型
-
- func (c *B) Cleanup(f func())
- 函数 (b *B) 已用() 时间。期间
- 函数 (c *B) 错误(参数 ...任何)
- func (c *B) Errorf(format string, args ...任何)
- func (c *B) Fail()
- func (c *B) FailNow()
- func (c *B) Failed() bool
- 函数 (c *B) 致命(参数 ...任何)
- func (c *B) Fatalf(格式字符串,参数...任何)
- 函数 (c *B) 助手()
- func (c *B) Log(args ...任何)
- func (c *B) Logf(format string, args ...任何)
- 函数 (c *B) 名称() 字符串
- func (b *B) ReportAllocs()
- func (b *B) ReportMetric(n float64, unit string)
- 函数 (b *B) 重置计时器()
- func (b *B) Run(name string, f func(b *B)) bool
- func (b *B) RunParallel(body func(*PB))
- func (b *B) SetBytes(n int64)
- func (b *B) SetParallelism(p int)
- func (c *B) Setenv(key, value string)
- func (c *B) Skip(args ...任何)
- func (c *B) SkipNow()
- func (c *B) Skipf(format string, args ...任何)
- func (c *B) Skipped() bool
- func (b *B) StartTimer()
- func (b *B) StopTimer()
- func (c *B) TempDir() 字符串
- 类型 基准测试结果
- 类型 封面
- 类型 盖块
- F型
-
- func (f *F) Add(args ...任何)
- func (c *f) Cleanup(f func())
- 函数 (c *F) 错误(参数 ...任何)
- func (c *f) Errorf(format string, args ...任何)
- func (f *F) Fail()
- func (c *f) FailNow()
- func (c *F) Failed() bool
- 函数 (c *F) 致命(args ...任何)
- func (c *f) Fatalf(format string, args ...任何)
- func (f *F) Fuzz(ff any)
- 函数 (f *F) 助手()
- func (c *f) log(args ...任何)
- func (c *f) Logf(format string, args ...任何)
- 函数 (c *F) 名称() 字符串
- func (c *F) Setenv(key, value string)
- func (c *f) Skip(args ...任何)
- func (c *f) SkipNow()
- func (c *F) Skipf(format string, args ...任何)
- func (f *F) Skipped() bool
- func (c *F) TempDir() 字符串
- 类型 内部基准测试
- 类型 内部示例
- 类型 内部模糊目标
- 类型 内部测试
- M型
- type PB
- type T
-
- func (c *T) Cleanup(f func())
- func (t *T) Deadline() (deadline time.Time, ok bool)
- func (c *T) Error(args ...any)
- func (c *T) Errorf(format string, args ...any)
- func (c *T) Fail()
- func (c *T) FailNow()
- func (c *T) Failed() bool
- func (c *T) Fatal(args ...any)
- func (c *T) Fatalf(format string, args ...any)
- func (c *T) Helper()
- func (c *T) Log(args ...any)
- func (c *T) Logf(format string, args ...any)
- func (c *T) Name() string
- func (t *T) Parallel()
- func (t *T) Run(name string, f func(t *T)) bool
- func (t *T) Setenv(key, value string)
- func (c *T) Skip(args ...any)
- func (c *T) SkipNow()
- func (c *T) Skipf(format string, args ...any)
- func (c *T) Skipped() bool
- func (c *T) TempDir() 字符串
- 结核病类型