在Go中,go test子命令是Go语言包的测试驱动程序,这些包根据某些约定组织在一起,在一个包目录中,以_test.go结尾的文件不是go build命令编译的目标,而是go test编译的目标。在*_test.go文件中,三种函数需要特殊对待,即功能测试函数、基准测试函数和示例函数。功能测试函数是以Test前缀命名的函数,用来检测一些程序逻辑的正确性,go test运行测试函数,并且报告结果是PASS还是FAIL。基准测试函数的名称以Benchmark开头,用来测试某些操作的性能,go test汇报操作的平均执行时间。go test工具扫描*_test.go文件来寻找特殊函数,并生成一个临时的main包来调用它们,然后编译和运行,并汇报结果,最后清空临时文件。
每一个测试文件都需要导入testing包,这些函数的函数签名格式是这样的:func TestName (t *testing.T) { //... } ,比如sin函数就是func TestSin(t *testing.T) {/* ... */},cos函数就是func TestCos(t *testing.T) {/* ... */}。测试可以让我们顺序地检查内容,如果一个测试套件(test suite)里面有很多测试用例,我们可以选择性地测试用例来加加测试过程。
命令-v可以输出包中每个测试用例的名称和执行的时间,命令-run的参数是一个正则表达式,它可以使得go test只有运行那些测试函数名称匹配给定模式的函数。当然,一旦我们使得选择的测试用例通过之后,在我们提交更改之前,我们必须重新使用不带开关的go test来运行一次整个测试套件。当调用t.Errorf输出的失败的调试用例信息没有包含整个跟踪栈信息,也不会导致程序宕机或者终止执行,这和很多其他语言的测试框架中的断言不同。测试用例彼此都是独立的,如果一个测试表中的一个条目造成测试失败,那么其他条目的测试仍然会继续测试,这样我们就会在一次测试过程中发现多个失败的情况,更方便我们进行错误的寻找。有的时候,我们需要中止测试,那么我们就可以使用t.Fatal或者t.Fatalf函数来终止测试。这些函数的调用必须和Test函数在同样一个goroutine中,而不能在测试用例创建的其他goroutine中。
测试错误信息一般的格式是f(X)=Y, want z,这里f(x)表示需要执行的操作和它的输入,y是实际的输出结果,z是期望得到的一个结果。处于方便,对于f(x)我们会使用Go的语法。在基于表的测试中,输出x是很重要的,因为一条断言语句会在不同的输入情况下执行多次,错误消息要避免样板文字和冗余信息。如果x、y、z都比较长,可以输出准确代表各部分的概要信息。