添加测试
一、说明
现在你已经把你的代码放到一个稳定的地方,添加测试。在开发期间当你做出改变,测试你的代码就能发现暴露的bugs。在这篇主题中,你将为Hello
函数添加测试。
Go对单元测试的内置支持让它更容易测试当你去做的时候。具体来说,使用命令约定。Go的testing
包,和go test
命令,你能快速写和执行测试。
-
在
greetings
目录中,创建一个文件叫做greetings_test.go
一个文件名以
_test.go
结尾,告诉go test
命令,这个文件包含测试函数。 -
在
greetings_test.go
文件中,粘贴下面的代码,并保存文件package greetings import ( "regexp" "testing" ) // TestHelloName 调用 greetings.Hello 带有一个name, 检查有效的返回值 func TestHelloName(t *testing.T) { name := "hef" want := regexp.MustCompile(`\b` + name + `\b`) msg, err := Hello(name) if !want.MatchString(msg) || err != nil { t.Fatalf(`Hello("hef") = %q, %v, want match for %#q, nil`, msg, err, want) } } // TestHelloEmpty 调用Hello, 传递一个空字符串,检查一个error func TestHelloEmpty(t *testing.T) { msg, err := Hello("") if msg != "" || err == nil { t.Fatalf(`Hello("") = %q, %v, want "", error`, msg, err) } }
在这个代码中:
- 实现了测试函数和你要测试的代码在相同的包里。
- 创建两个测试函数去测试
greetings.Hello
函数。测试函数的命名有格式:TestName
。这里的Name是说某个特定东西的测试。测试函数获得一个指针作为参数,指向testing
包的testing.T
类型。您可以使用此参数的方法来报告和记录您的测试。 - 实现了两个测试:
TestHelloName
调用Hello
函数,传递一个name
值,带有一个函数应该返回的有效值。如果调用返回一个错误或一个未期待的响应消息(不包含你传递进去的名字),你使用t
参数的Fatalf
方法去打印一个消息到控制台,并结束执行。TestHelloEmpty
调用Hello
函数,传递一个空值。这个测试被设计用来验证你的错误处理。如果调用返回一个非空的字符串或不是一个错误,你使用t参数的Fatalf
方法去打印一条消息到控制台,并结束执行。
-
在
greetings
目录到命令行下,运行go test
命令去执行测试那个
go test
命令执行在文件(名称以_test.go
结尾)中的测试函数(以Test
开头)。你能添加一个-v
标识去获取一个冗长的输出,列出所有的测试和它们的测试结果。这些测试应该通过。
$ go test PASS ok example.com/greetings 0.573s $ go test -v === RUN TestHelloName --- PASS: TestHelloName (0.00s) === RUN TestHelloEmpty --- PASS: TestHelloEmpty (0.00s) PASS ok example.com/greetings 0.117s $
-
破环
greetings.Hello
函数,展示一个错误的测试TestHelloName
测试函数检查返回值,为你指定的name作为Hello
函数参数。为了展示一个错误的测试结果,改变greetings.Hello
函数,以至于它不包含一个name。在
greetings/greetings.go
文件中,粘贴下面的代码替换Hello
函数。请注意,突出显示的行会更改函数返回的值,就好像 name 参数被意外删除了一样。// Hello 为一个命名的人返回一个问候 func Hello(name string) (string, error) { // 如果没有给出name,返回一个带有消息的错误 if name == "" { return "", errors.New("empty name") } // 如果接受到一个名字,返回一个问候,嵌套名字在消息中 // message := fmt.Sprintf("Hi, %v. Welcome!", name) // 使用随机消息格式创建消息 // message := fmt.Sprintf(randomFormat(), name) message := fmt.Sprintf(randomFormat()) return message, nil }
-
在
greetings
目录的命令行中,运行go test
命令去执行测试这次,运行
go test
不带-v
标识。那输出将仅包含测试失败的结果,当你有很少的测试时,这种方法是有用的。那个TestHelloName
测试将失败,TestHelloEmpty
仍然将通过。$ go test --- FAIL: TestHelloName (0.00s) greetings_test.go:14: Hello("hef") = "Great to see you, %!v(MISSING)!", <nil>, want match for `\bhef\b`, nil FAIL exit status 1 FAIL example.com/greetings 0.606s $