本文翻译自《Add a test》。
现在你已经将代码放到了一个稳定的位置(顺便说一句,做得很好),接下来添加一个测试。在开发期间测试你的代码,可以发现更改代码造成的Bug。在本文中,你将为Hello
函数添加一个测试。
注意:本主题是从《创建一个Go模块》开始的多部分教程的一部分。
Go对单元测试的内置支持使你可以轻松地进行测试。具体来说,使用命名约定、Go的testing
和go test
命令,你可以快速编写和进行测试。
1 在greetings目录中,创建一个名为greetings_test.go的文件。
以_test.go结尾的文件名告诉go test
命令该文件包含测试函数。
2 在greetings_test.go中,粘贴以下代码并保存文件。
package greetings
import (
"testing"
"regexp"
)
// TestHelloName函数使用一个名字name调用greetings.Hello函数,检查返回值是否有效。
func TestHelloName(t *testing.T) {
name := "Gladys"
want := regexp.MustCompile(`\b`+name+`\b`)
msg, err := Hello("Gladys")
if !want.MatchString(msg) || err != nil {
t.Fatalf(`Hello("Gladys") = %q, %v, want match for %#q, nil`, msg, err, want)
}
}
// TestHelloEmpty函数传入空字符串调用greetings.Hello函数,检查是否会发生错误。
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
值,应该能够返回有效的响应消息。如果返回一个错误或一个意外消息(不包含你传入的name
值),你可以使用t
参数的Fatalf
方法将消息打印到控制台并结束执行。
TestHelloEmpty
函数使用空字符串调用Hello
函数。此测试旨在确认你的错误处理是否有效。如果返回非空字符串或没有错误,则使用t
参数的Fatalf
方法将消息打印到控制台并结束执行。
3 在greetings目录下命令行运行go test
命令执行测试。
go test
命令执行测试文件(名称以_test.go结尾)中的测试函数(名称以Test
开头)。你可以添加-v
标志以获得所有测试及其结果的详细输出。
本测试应该可以通过。
$ go test
PASS
ok example.com/greetings 0.364s
$ go test -v
=== RUN TestHelloName
--- PASS: TestHelloName (0.00s)
=== RUN TestHelloEmpty
--- PASS: TestHelloEmpty (0.00s)
PASS
ok example.com/greetings 0.372s
4 破坏greetings.Hello
函数以查看失败的测试结果。
测试TestHelloName
函数检查你传递name
参数给Hello
函的返回值。要查看失败的测试结果,请更改greetings.Hello
函数,使返回值中不再包含name
参数的值。
在greetings/greetings.go中,粘贴以下代码代替Hello
函数。请注意,突出显示的行更改该函数返回的值,就好像name
参数被意外删除一样。
// Hello函数返回对指定名字的人员的一句问候语。
func Hello(name string) (string, error) {
// 如果name参数的值为空字符串,返回一个错误信息。
if name == "" {
return name, errors.New("empty name")
}
// 使用一个随机格式创建一个消息。
// message := fmt.Sprintf(randomFormat(), name)
message := fmt.Sprint(randomFormat())
return message, nil
}
5 在greetings目录下命令行运行go test
命令执行测试。
这次,在没有-v
标志的情况下运行go test
。输出将仅包含失败测试的结果,这在你有大量测试时很有用。测试TestHelloName
函数应该会失败——测试TestHelloEmpty
函数仍然会通过。
$ go test
--- FAIL: TestHelloName (0.00s)
greetings_test.go:15: Hello("Gladys") = "Hail, %v! Well met!", <nil>, want match for `\bGladys\b`, nil
FAIL
exit status 1
FAIL example.com/greetings 0.182s
在下一个(也是最后一个)主题中,你将了解如何编译和安装代码以在本地运行它。