零基础学习Go的Day12| 青训营笔记

86 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 12 天

1.复习已学知识

  • 复习并发编程的基本知识
  • 复习Goroutine
  • 复习WaitGroup
  • 复习Lock
  • 复习Channel
  • 复习依赖管理

2.观看Go语言进阶与依赖管理

  • Go 与单元测试

为什么需要测试,什么是单元测试

通常,对于一个玩具项目,我们喜欢将其写完后直接部署到生产环境,有 Bug 在修,但是,这对于企业开发来说是完全不能忍受的,因为一个小小的 Bug 便可带来天文数字的损失。因此,在程序上线前进行测试对于企业开发来说便是一个必要的活动。

通常,有多种测试方法可以使用,例如回归测试,集成测试,单元测试,而单元测试(Unit Test) 是成本最低,覆盖率最高的测试方法。所谓单元测试,便是为代码的每一个模块,函数定制单独的测试,保证输入指定值后输出正常值。通过多个单元测试合并运作,我们便可得知项目的每一个细节都在正确运行,最终得知项目整体运作正常。

进行单元测试

Go 内置单元测试支持。所有以 _test.go 结尾的代码会被 Go 识别为单元测试文件。

一个单元测试函数的函数名应当以 Test 开头,并包含 *testing.T 形参。

可通过 func TestMain(m *testing.M) 函数对测试数据进行初始化,并调用 m.Run() 运行单元测试。

以下代码是一个简单的单元测试例子,测试 HelloTom 函数是否正常返回值 Tom

// In xxx.go:
func HelloTom() string {
    return "Jerry"
}
​
// In xxx_test.go:
func TestHelloTom(t *testing.T) {
    output := HelloTom()
    expectOutput := "Tom"
    if output != expectOutput {
        t.Errorf("Expected %s do not match actual %s", expectOutput, output)
    }
}

并使用 go test 指令运行单元测试,得到运行失败的输出:

=== RUN   TestHelloTom
    xxx_test.go:9: Expected Tom do not match actual Jerry
--- FAIL: TestHelloTom (0.00s)

当然,我们也可以引入社区提供的依赖库来加快单元测试开发,诸如通过 testify/assert 库进行覆盖率测试,或通过 bouk/monkey 库对数据进行 Mock。此处不再赘述。

基准测试

有时,我们想要测量一个函数执行不同次数,或是在不同环境下执行函数的性能,这时,就需要进行基准测试。Go 内置基准测试支持。

以下代码模拟了一个负载均衡的例子,在 10 个服务器中随机返回数据,我们将对 Select 方法分别进行串行和并行的基准测试:

// In xxx.go:
import "math/rand"
​
var ServerIndex [10]int
​
func InitServerIndex() {
    for i := 0; i < 10; i++ {
        ServerIndex[i] = i + 100
    }
}
func Select() int {
    return ServerIndex[rand.Intn(10)]
}
​
// In xxx_test.go:
package main
​
import "testing"
​
func BenchmarkSelect(b *testing.B) {
    InitServerIndex()
    b.ResetTimer() // 重置计数器是因为 InitServerIndex 不应包含在测试时间内
    for i := 0; i < b.N; i++ {
        Select()
    }
}
func BenchmarkSelectParallel(b *testing.B) {
    InitServerIndex()
    b.ResetTimer()
    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            Select()
        }
    })
}

并使用 go test -bench= 指令运行基准测试,得到结果:

GOROOT=F:\Program Files\Go #gosetup
GOPATH=C:\Users\shaok\go #gosetup
"F:\Program Files\Go\bin\go.exe" test -c -o C:\Users\shaok\AppData\Local\Temp\GoLand___gobench_helloWorld.test.exe helloWorld #gosetup
C:\Users\shaok\AppData\Local\Temp\GoLand___gobench_helloWorld.test.exe -test.v -test.paniconexit0 -test.bench . -test.run ^$ #gosetup
goos: windows
goarch: amd64
pkg: helloWorld
cpu: AMD Ryzen 7 5800H with Radeon Graphics
BenchmarkSelect
BenchmarkSelect-16              164467417                7.332 ns/op
BenchmarkSelectParallel
BenchmarkSelectParallel-16      26950542                43.85 ns/op
PASS

根据基准测试结果,我们可以进行针对性的优化。