跳转到主要内容
模块 9 · 第 1 课(共 5)课程中的41/50~12 min
模块课程(1/5)

“测试”包

在 Go 中,测试是 stdlib 的一部分*_:没有外部库,没有要配置的框架。您所需要的只是代码旁边的 _\_test.go文件、一些TestXxx函数和go test 命令。

基本约定

  • 测试文件被命名为 <something>_test.go ,并且与它们测试的代码位于相同的包中(或者位于 <name>_test 包中以进行“黑盒测试”)。
  • 测试函数有一个精确的签名:func TestXxx(t *testing.T),其中Xxx以大写字母开头。
  • 您从 stdlib 导入 testing。
  • 否 assertEquals:您将 if got != want { t.Errorf(...) } 与 fmt 动词一起使用。
Go
// math.go
package math

func Sum(a, b int) int { return a + b }

// math_test.go
package math

import "testing"

func TestSum(t *testing.T) {
    got := Sum(2, 3)
    if got != 5 {
        t.Errorf("Sum(2,3) = %d; voglio %d", got, 5)
    }
}

运行它:

Bash
go test ./...        # all packages in the module
go test -v ./pkg     # verbose: prints test names
go test -run TestSum  # only tests matching the regex

t.Error 与 t.Fatal

这是表示失败的两个基本动词:

方法效果
t.Log(args...)记录但不会失败(仅在使用 -v 或失败时可见)。
t.Error(args...)记录、标记“失败”、继续测试功能。
t.Errorf(fmt, ...)就像带有格式的 Error 一样。
t.Fatal(args...)记录、标记“失败”、停止测试(调用 runtime.Goexit)。
t.Fatalf(fmt, ...)t.Fatalf(fmt, ...)就像带有格式的 Fatal 一样。

经验法则:当继续没有意义时使用 Fatal (例如,设置失败、即将发生 nil 指针取消引用);否则**Error**,它可以让您在单次运行中查看所有失败。

Go
func TestOpen(t *testing.T) {
    f, err := os.Open("fixtures/sample.txt")
    if err != nil {
        t.Fatal(err) // if it doesn't open, the next steps would fail on nil
    }
    defer f.Close()
    // ... assert on content with t.Errorf
}

使用 t.Cleanup 设置和拆卸

要在测试(或子测试)结束时释放资源,请使用 t.Cleanup 而不是 defer:

Go
func TestDB(t *testing.T) {
    db := newTestDB(t)
    t.Cleanup(func() { db.Close() })
    // ... test
}

相对于 defer 的优点:创建 db 的帮助程序可以内部注册清理,因此调用者不需要记住它。

测试助手

t.Helper() 方法将函数标记为“助手”:当测试失败时,堆栈跟踪跳过助手函数并直接指向调用者:

Go
func mustParseInt(t *testing.T, s string) int {
    t.Helper()
    n, err := strconv.Atoi(s)
    if err != nil {
        t.Fatalf("parse %q: %v", s, err)
    }
    return n
}

练习

锻炼#go.m9.l1.e1
尝试:0加载中...

定义 TestSum 函数,使用 t.Errorf 和格式化消息来验证 Sum(2,3) == 5。

正在加载编辑器...

3 次尝试后可用的解决方案

锻炼#go.m9.l1.e2
尝试:0加载中...

在 TestDiv 中,如果 Div 返回意外值,请使用 t.Fatal 立即停止测试。

正在加载编辑器...

3 次尝试后可用的解决方案

Quiz#go.m9.l1.e3
准备好

t.Error 和 t.Fatal 之间的根本区别是什么?

Go
if err != nil {
  t.???(err)
}
答案选项