编写你的第一个测试
学习使用 Go 编写测试的基础知识。
简介
我们从 Go 语言中测试的一个基本示例开始。下面是一个我们希望进行测试的简单函数:
1package helloworld 2 3func Sum(a, b int) int { 4 return a + b 5}
该函数名为 Sum,接收两个类型为 int 的参数 a 和 b。它将两者相加并返回结果。最后,该函数属于 helloworld 包。让我们看看如何为它定义一个基本测试:
No configuration found for ID: be0d3d9ba54a0f8ca40932734a1f0c5e4a3f21c044abed109924801bc6783bbd
上述示例只涉及两个文件:
main.go文件包含实际代码。在我们的例子中,它仅由Sum函数组成。main_test.go文件包含用于评估Sum函数正确行为的测试代码。
要执行某个包中的测试,我们需要运行 go test 命令,该命令会显示测试的结果:PASS 或 FAIL。如果我们希望获得更详细的输出,包括通过的测试列表,则需要使用 go test -v。
注意:使用
go test命令时,仅运行当前包中定义的测试。换句话说,只有在终端所在目录下的测试才会被执行。若要运行整个模块的所有测试,应使用go test ./...。
现在,让我们聚焦于测试代码,以便更好地理解它。首先,这被称为白盒测试,因为测试代码与生产代码位于同一个包中(本例中为 helloworld 包)。在白盒测试中,我们可以在测试函数中访问生产代码中定义的所有内容(包括未导出的部分)。
注意:白盒测试的反面是黑盒测试。要实现黑盒测试,我们需要将测试代码写在与生产代码不同的包中。在我们的例子中,可以创建一个名为
helloworld_test的包来遵循 Go 的命名规范。这样,我们就无法访问内部实现,只能使用导出的值和函数。
在 Go 语言中,我们无需依赖外部测试框架,因为所有测试所需的功能都已内置在语言中。只需导入 testing 包,即可开始编写测试。
命名规范
测试中的另一个重要方面是命名规则。以下是需要遵循的良好命名规范:
- 测试函数的名称必须采用
TestXxx格式,其中Xxx是被测试函数的首字母大写名称。 - 通常,SUT 指的是“被测系统”,即我们正在测试的组件。这通常是带有若干方法的结构体,我们可以对其实例进行调用。
- 通常,
got表示被测系统返回的结果。这个结果需要被断言,以检查其是否符合预期。
失败的测试
测试执行可能有两种结果:成功或失败。如果测试函数代码执行过程中没有引发任何错误,则调用成功。然而,当预期结果未满足时,我们也可以将测试标记为失败。要将测试标记为失败,需要在 t 结构体上调用 Errorf。Errorf 还接受格式化模板,因此我们可以传入数据,输出更有意义的信息给用户。下面我们故意在之前的代码中引入一个小错误,以演示一个失败的测试:
No configuration found for ID: 4e036bc80c9baec83418747714686f2013f3b7da8744d02e7e7fb5b5c57b5470
在上面的代码示例中,我们故意在 Sum 函数中引入了一个错误:不是相加,而是相减。由于这个小错误,我们可以看到失败测试的输出结果。当我们运行测试时,会得到提示 main_test.go:8 expected to get 3 but got -1。这条消息非常清晰,使我们能够轻松定位问题所在并加以修复。