go语言之自动化测试
为什么需要自动化测试?
- 确保代码质量:自动化测试可以确保代码在修改后仍然按照预期工作。每当你更改代码时,自动化测试可以快速地检查是否有任何回归错误,从而帮助你保持代码的稳定性和可靠性。
- 提高开发效率:通过自动化测试,你可以快速地运行大量的测试用例,这比手动测试要高效得多。这样可以节省时间,让你专注于编写新功能和改进代码,而不是在调试上花费过多时间。
- 文档作用:测试用例本身可以作为代码的一种文档。它们展示了如何使用特定的函数或模块,以及预期的行为是什么。这对于新加入项目的开发者来说尤其有用。
- 促进模块化和可维护性:良好的测试用例鼓励开发者编写模块化和易于测试的代码。这样的代码结构清晰,更易于维护和扩展。
- 减少风险:在代码合并到主分支之前运行自动化测试可以减少引入错误的风险。这有助于保护代码库的整体健康,并确保只有经过验证的代码被合并
golang提供了一个testing包用于为代码编写自动化测试,还有go test 命令,用于运行这些测试,包的用法可通过如下命令查看:
go doc testing
例子:定义yi.go文件,包含一个函数abcd,接收字符串切片并将切片除了最后一个元素外都使用逗号连接,然后通过and 和最后一个元素连接,如图:

定义测试文件yi_test.go,编写测试函数,预期的输出结果为expected的值,如图:

上图中的测试文件和正式文件都在同一包main中,也可以不放在同一个包中,但是调用函数abcd()的时候就需要使用包名来调用了,测试yi_test.go中应该遵循的规则如下:
- 测试文件的顶部需要导入testing包
- 测试函数应该以Test开头,后面的部分可自定义即可
- 测试函数接收单个参数,一个指向testing.T的指针,T 是一个结构体
- 可通过调用 T 结构体中的Error方法来输出测试失败信息
通过go test命令来运行测试,go test命令将在包目录中找到所有名字以_test.go结尾的文件,并运行文件中以Test开头的每个函数
yi_test.go中预期yi.go中的结果,然后测试世界结果是否与预期匹配,下面是go test指定文件,如图:

结果返回ok,说明预期结果与实际结果匹配,测试成功
注:如果直接执行go test也可以,不过此时运行的是全部的_test.go文件
修改yi.go中的连接方式,在and前面添加一个逗号,如图:

查看结果,已经报错,说明与预期结果不匹配,如图:

除了Error方法,还有一个Errorf方法,Errorf接收一个带格式化动词的字符串,类似fmt.Sprintf和fmt.Printf,因此可以在打印结果中传递变量或者参数
修改yi_test.go,将Error修改为Errorf,如图:

打印结果如图:

如果测试函数比较多,每个都调用t.Error打印内容会出现重复代码,此时可定义一个函数来减少代码重复,如图:

如上图,单独定义一个errorPrintf函数,然后通过return返回给t.Error()
注:go test命令只会处理以_test.go结尾的文件,go build 和 go install 也会忽略名称以_test.go结尾的文件
如果yi_test.go中包含多个测试函数,此时指向运行特定的函数,那么就可以使用-run,如图:

- -run Abcd 表示运行名字中包含Abcd的函数
- -v 表示输出详细信息,可不加,加了更详细
注:也可以不用指定文件,直接执行go test -v -run Abcd即可
多函数示例
修改yi_test.go文件,新增一个TestEfgh测试函数,如图:

- 定义三个元素的切片b
- 期望值为前两个元素逗号连接,第三个的元素的and前面也要用逗号
运行测试,查看执行结果,如图:

从上图看出,第一个函数TestAbcd测试成功,第二个TestEfgh测试失败,因为实际与预期不符,少了一个逗号,说明我们的abcd()函数只能符合满足传递包含2个元素的切片,传递超过2个元素的切片不行,此时需要修改abcd函数,让它可以满足2个元素和2个以上元素,如图:

再次运行测试,可以发现两个函数都可以成功,如图:

表驱动测试
上面的两个测试函数中有很多重复的部分,如图:

不需要维护每一个单独测试函数,可以构建一个由输入数据和期望的输出组成的 “表”,然后使用单个测试函数检查表中的每一项,表没有标准格式,常见的用法是定义一个新的结构体类型,定义一个list字段保存要传递给abcd的字符串切片,以及一个expected字段保存期望的返回字符串

将TestAbcd()和TestEfgh()去掉,只定义一个函数TestOne(),定义一个结构体切片tests,每个切片都是一个testMethod结构体,结构体中list字段就是要传递的切片,循环遍历结构体切片,将list切片传递给abcd(),如图:

更新后的代码更加简洁,执行go test测试,如图:

后续如果要新增传递的切片数据,只需要修改tests切片即可,然后测试
注意:如果要测试的函数中还调用了其他文件中的函数,那么在执行go test的时候,直接执行go test -v TestAbcd()名即可运行指定函数(简单快捷),如果要指定文件,那么需要加上全部文件,否则会提示函数找不到,如:
go test a_test.go a.go b.go c.go //把相关文件全部加上才行


