GO 单元测试
简介
单元测试是为了对函数或者模块的功能进行测试。以往,我们在调试程序的时候,是有main函数的,在main函数中对函数进行调用,然后观察运行结果是否正确。
但是实际项目开发中,这样的操作手段存在很多隐患:
- 多个测试用例在main中进行调用时,为了不调用某个测试用例就需要先注释掉然后再运行main
- 由于在main中修改,会影响到程序主体架构,这样不利于版本的构建
所以Go引入了Testing测试框架来进行单元测试。
基本规则
- 为了使用Testing,需要引入Testing包。
- 文件名以_test.go结尾是测试文件。
- 在 _test.go 中编写测试用例时,函数以Test开头,且Test之后第一个字母不能是小写字母,因为go识别Test是根据驼峰命名法识别的。
- 运行_test.go文件的方法是在测试文件所在目录下,输入命令go test
- go test和go test -v的区别是前者仅在有错误的情况下才会输出详细信息(正确仅输出PASS),后者是任何情况都会输出详细信息
例子
例子是查找数组中的值,常规方法是O(N),而排序后使用二分法是O(NlogN)(排序算法是O(NlogN)+二分是O(logN))。
在工程下新建Search文件夹,下面新建Search.go和Search_test.go文件
Search.go
package Search
import "sort"
func BinarySearch1(arr []int,val int) bool{
for i:=0;i<len(arr);i++{
if arr[i]==val{
return true
}
}
return false
}
func BinarySearch2(arr []int,val int) bool{
sort.Slice(arr, func(i, j int) bool {
return arr[i]<arr[j]
})
ind:=sort.Search(len(arr), func(i int) bool {
return arr[i]<val
})
if ind<len(arr) && arr[ind]==val{
return true
}
return false
}
Search_test.go
package Search
import (
"log"
"testing"
)
func TestBinarySearch1(t *testing.T) {
arr:=[]int{1,2,3,4,5}
val:=5
if !BinarySearch1(arr,val){
log.Fatalln("期望返回true,实际上返回false",val)
}
val=6
if BinarySearch1(arr,val){
log.Fatalln("期望返回false,实际上返回true",val)
}
}
func TestBinarySearch2(t *testing.T) {
arr:=[]int{1,2,3,4,5}
val:=5
if !BinarySearch2(arr,val){
log.Fatalln("期望返回true,实际上返回false")
}
val=6
if BinarySearch2(arr,val){
log.Fatalln("期望返回false,实际上返回true")
}
}
上面Search_Test.go中的log.Fatalln就可以在有错误的情况下报错,从而告知Testing框架是否PASS
命令
go test -v
输出
=== RUN TestBinarySearch1
--- PASS: TestBinarySearch1 (0.00s)
=== RUN TestBinarySearch2
2021/08/14 16:48:09 期望返回true,实际上返回false
exit status 1
FAIL awesomeProject/Search 0.305s
上述可以看见第二个用例没有通过,说明代码出现问题
那么我们在修改部分错误代码修改后(修改可以通过调试,goland是支持调试测试函数的)
func BinarySearch2(arr []int,val int) bool{
sort.Slice(arr, func(i, j int) bool {
return arr[i]<arr[j]
})
ind:=sort.Search(len(arr), func(i int) bool {
return arr[i]>=val
})
if ind<len(arr) && arr[ind]==val{
return true
}
return false
}
如果我们只想测试第二个测试用例可以使用如下命令
命令
go test -v -test.run TestBinarySearch2
输出
=== RUN TestBinarySearch2
--- PASS: TestBinarySearch2 (0.00s)
PASS
ok awesomeProject/Search 0.323s
实际上,如果在目录下存在多个测试用例文件,我们还可以指定测试文件,注意一定要带上测试的源文件
命令
go test -v Search_test.go Search.go
输出
=== RUN TestBinarySearch1
--- PASS: TestBinarySearch1 (0.00s)
=== RUN TestBinarySearch2
--- PASS: TestBinarySearch2 (0.00s)
PASS
ok command-line-arguments 0.258s
上面的输出标出了几个时间,虽然看起来两个函数运行时间都是0.00s(太快以至于可以忽略不计)但是最后总时间是0.258s,这是因为Testing测试框架运行还需要时间。
如果我将测试用例改为如下:
func TestBinarySearch1(t *testing.T) {
arr:=[]int{1,2,3,4,5}
for i:=0;i<100000;i++{
arr=append(arr,i)
}
val:=99999
if !BinarySearch1(arr,val){
log.Fatalln("期望返回true,实际上返回false")
}
val=100000
if BinarySearch1(arr,val){
log.Fatalln("期望返回false,实际上返回true")
}
}
func TestBinarySearch2(t *testing.T) {
arr:=[]int{1,2,3,4,5}
for i:=0;i<100000;i++{
arr=append(arr,i)
}
val:=99999
if !BinarySearch2(arr,val){
log.Fatalln("期望返回true,实际上返回false")
}
val=100000
if BinarySearch2(arr,val){
log.Fatalln("期望返回false,实际上返回true")
}
}
命令
go test -v Search_test.go Search.go
输出
=== RUN TestBinarySearch1
--- PASS: TestBinarySearch1 (0.01s)
=== RUN TestBinarySearch2
--- PASS: TestBinarySearch2 (0.06s)
PASS
ok command-line-arguments 0.389s
可以看出时间的差别。
本文作者:WinterStarHu Go语言
本文链接:https://WinterStarHu.github.io/post/go-dan-yuan-ce-shi/
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
本文链接:https://WinterStarHu.github.io/post/go-dan-yuan-ce-shi/
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!