您诸位好啊,我是“菜鸟哥”--无尘,最早能看到这篇文章的小伙伴,也应该是中秋假期第一天了,首先祝大家中秋愉快,也感谢大家这么久以来的关注和支持。
在此佳节之际,作为回报,没有领到大闸蟹的, 可以在文章底部加我下微信,我来告诉你如何正确地吃一只大闸蟹?哈哈哈哈... 嗝~(留言有机会得红包)
对于 Go 语言的测试,我们之前写过一篇文章,简单介绍了下:单元测试,确保高质量代码的秘诀!,今天再来详细的介绍下。
目前 Go 测试系统支持单元测试、性能测试和示例测试:
单元测试就是对单元进行测试,一个单元可以是一个函数、一个模块等。
目录结构如下所示:
[ceshi]
|--[gotest]
|--unit.go
|--[gotest_test]
|--unit_test.go
unit.go
为源代码文件, unit_test.go
为测试文件。测试文件必须以“_test.go”
结尾。
源代码文件 unit.go 代码:
package gotest
func Add(a, b int) int {
return a + b
}
测试文件 unit_test.go 代码:
package gotest_test
import (
"ceshi/gotest"
"testing"
)
func TestAdd(t *testing.T){
var a = 1
var b = 2
var expected = 3
actual := gotest.Add(a, b)
if actual != expected {
t.Errorf("Add(%d, %d) = %d; expected: %d", a, b, actual, expected)
}
}
测试文件可以跟源文件在同一个包,但多数情况是创建一个包专用于测试,这样可以使测试文件和源文件隔离。GO源代码以及其他知名的开源框架通常会创建测试包,而且规则是在原包名上加上”_test”。
在测试文件所在目录中,使用 go test
命令即可启动单元测试,如下所示:
$ go test
PASS
ok ceshi/gotest_test 0.818s
❝单元测试规则:
❞
基准测试函数和普通测试函数写法类似,但是以Benchmark
为前缀名,并且带有一个*testing.B
类型的参数;*testing.B
参数除了提供和*testing.T
类似的方法,还有额外一些和性能测量相关的方法。它还提供了一个整数 N,用于指定操作执行的循环次数。
目录结构如下所示:
[ceshi]
|--[gotest]
|--benchmark.go
|--[gotest_test]
|--benchmark_test.go
benchmark.go
为源代码文件, benchmark_test.go
为测试文件。
源代码文件 benchmark.go 代码:
package gotest
//不预分配
func Slice1() []int {
var newSlice []int
for i := 0; i < 100000; i++ {
newSlice = append(newSlice, i)
}
return newSlice
}
//预分配Slice的存储空间构造
func Slice2() []int {
var newSlice []int
newSlice = make([]int, 0, 100000)
for i := 0; i < 100000; i++ {
newSlice = append(newSlice, i)
}
return newSlice
}
两个方法都构造一个容量 100000 的切片,所不同的是 Slice1() 不预先分配内存, Slice2() 会预先分配内存,本次来测试一下二者的性能差异。
测试文件 benchmark_test.go 代码:
package gotest_test
import (
"ceshi/gotest"
"testing"
)
func BenchmarkSlice1(b *testing.B) {
for i := 0; i < b.N; i++ {
gotest.Slice1()
}
}
func BenchmarkSlice2(b *testing.B) {
for i := 0; i < b.N; i++ {
gotest.Slice2()
}
}
$ go test -bench=.
goos: windows
goarch: amd64
pkg: ceshi/gotest_test
cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
BenchmarkSlice1-12 2539 474179 ns/op
BenchmarkSlice2-12 10000 109779 ns/op
PASS
ok ceshi/gotest_test 4.018s
其中 -bench
为 go test 的 flag,该 flag 指示 go test 进行性能测试。
通过输出可以直观的看出, BenchmarkSlice1 执行了2539次,平均每次 474179 纳秒, BenchmarkSlice2 执行了10000次,平均每次 109779 纳秒。
从测试结果上看,虽然构造切片很快,但通过给切片预分配内存,性能还可以进一步提升,符合预期。
❝性能测试规则:
❞
目录结构如下所示:
[ceshi]
|--[gotest]
|--example.go
|--[gotest_test]
|---example_test.go
example.go
为源代码文件, example_test.go
为测试文件。
源代码文件 example.go 代码:
package gotest
import "fmt"
//一行打印输出
func SayHello() {
fmt.Println("Hello 微客鸟窝")
}
//两行打印输出
func SayGoodbye() {
fmt.Println("微客鸟窝,")
fmt.Println("goodbye")
}
//多行打印输出,由于Map数据结构的原因,多行打印次序是随机的。
func PrintName() {
name := make(map[int]string, 4)
name[1] = "微"
name[2] = "客"
name[3] = "鸟"
name[4] = "窝"
for _, value := range name {
fmt.Println(value)
}
}
测试文件 example_test.go 代码:
package gotest_test
import "ceshi/gotest"
func ExampleSayHello() {
gotest.SayHello()
// OutPut: Hello 微客鸟窝
}
func ExampleSayGoodbye() {
gotest.SayGoodbye()
// OutPut:
// 微客鸟窝,
// goodbye
}
func ExamplePrintName() {
gotest.PrintName()
//Unordered output:
//微
//客
//鸟
//窝
}
例子测试函数命名规则为”Examplexxx”,其中”xxx”为自定义的标识,通常为待测函数名称。
$ go test example_test.go
ok command-line-arguments 0.605s
❝示例测试规则:
❞
图片及部分相关技术知识点来源于网络搜索,侵权删!
参考资料:
https://kaiwu.lagou.com/course/courseInfo.htm?sid=&courseId=536&lagoufrom=noapp#/sale
《Go专家编程》
http://shouce.jb51.net/gopl-zh/ch10/ch10-07.html