编写测试代码

在这节,您将了解怎样给一个存在的 Go 应用写测试,它有俩个函数:一个是计算斐波纳切数,一个是计算一个字符串长度。使用这俩个函数的主要原因是比较简单,它们实现了相对琐碎的任务。琐碎点是每个函数有俩个不同的实现:一个工作的很好,另一个有些问题。

这个例子 Go 包命名为 testMe,并存为 testMe.go。这个包的代码将分为三部分来介绍。

testMe.go 的第一部分代码如下:

  1. package testMe
  2. func f1(n int) int {
  3. if n == 0 {
  4. return 0
  5. }
  6. if n == 1 {
  7. return 1
  8. }
  9. return f1(n-1) + f1(n-2)
  10. }

从上面的代码,您能看到定义了一个名为 f1() 函数,用来计算斐波纳切数。

testMe.go 的第二段代码如下:

  1. func f2(n int) int {
  2. if n == 0 {
  3. return 0
  4. }
  5. if n == 1 {
  6. return 2
  7. }
  8. return f2(n-1) + f2(n-2)
  9. }

这段代码,您能看到另一个名为 f2() 的函数实现计算斐波纳切数。然而,这个函数有一个错误,因为在 n1时,它没有返回 1,这毁掉了函数的整个功能。

testMe.go 的其余代码如下:

  1. func s1(s string) int {
  2. if s == "" {
  3. return 0
  4. }
  5. n := 1
  6. for range s {
  7. n++
  8. }
  9. return n
  10. }
  11. func s2(s string) int {
  12. return len(s)
  13. }

这部分,我们实现了俩个函数,分别为 s1()s2(),用来处理字符串。它们都返回字符串长度。然而,s1() 的实现是错误的,因为 n 的初始值是 1 而不是 0。

现在开始考虑测试和测试用例。首先,您应该创建一个名为 testMe_test.go 的文件来存放您的测试代码。接着,重要的是认识到您不需要对 testMe.go的代码做任何改变。最后,记住您应该根据需要尽可能多的编写测试函数来覆盖所有潜在的输入和输出。

testMe_test.go 的第一部分如下:

  1. package testMe
  2. import "testing"
  3. func TestS1(t *testing.T) {
  4. if s1("123456789") != 9 {
  5. t.Error(`s1("123456789") != 9`)
  6. }
  7. if s1("") != 0 {
  8. t.Error(`s1("") != 0`)
  9. }
  10. }

上面的函数对 s1() 函数执行俩个测试:一个使用 "123456789" 作为输入,另一个用 "" 作为输入。

testMe_test.go 的第二部分如下:

  1. func TestS2(t *testing.T) {
  2. if s2("123456789") != 9 {
  3. t.Error(`s2("123456789") != 9`)
  4. }
  5. if s2("") != 0 {
  6. t.Error(`s2("") != 0`)
  7. }
  8. }

上面对测试代码对 s2() 函数执行同样的俩个测试。

testMe_test.go 的其余代码如下:

  1. func TestF1(t *testing.T) {
  2. if f1(0) != 0 {
  3. t.Error(`f1(0) != 0`)
  4. }
  5. if f1(1) != 1 {
  6. t.Error(`f1(1) != 1`)
  7. }
  8. if f1(2) != 1 {
  9. t.Error(`f1(2) != 1`)
  10. }
  11. if f1(10) != 55 {
  12. t.Error(`f1(10) != 55`)
  13. }
  14. }
  15. func TestF2(t *testing.T) {
  16. if f2(0) != 0 {
  17. t.Error(`f2(0) != 0`)
  18. }
  19. if f2(1) != 1 {
  20. t.Error(`f2(1) != 1`)
  21. }
  22. if f2(2) != 1 {
  23. t.Error(`f2(2) != 1`)
  24. }
  25. if f2(10) != 55 {
  26. t.Error(`f2(10) != 55`)
  27. }
  28. }

上面的代码测试了 f1()f2() 函数的操作。

执行测试将产生如下输出:

11.7.1 编程测试代码 - 图1

如果您没使用 -v 参数(产生详细输出),您将得到如下输出:

11.7.1 编程测试代码 - 图2

您希望执行某些测试用例的话,您应该使用 -run 命令行选项,它接收一个正则表达式并执行所有函数名与给定正则表达式匹配的测试。

11.7.1 编程测试代码 - 图3

最后的命令验证了 go test 命令使用了缓存。

软件测试只能显示一个或多个 bug 的存在,而不是没有 bug !这意味着您绝不能绝对确定代码没有 bug 。