Go 语言测试性能 | 青训营笔记

83 阅读3分钟

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

测试

go test 指定文件时默认执行文件内的所有测试用例。可以使用-run参数选择需要的测试用例单独执行。-v 可以使得输出的更详细

测试是避免事故的最后一道屏障

回归测试->集成测试->单元测试,从左到右,覆盖率逐层变大,成本却逐层降低

回归测试:比如刷一下抖音看看正不正常

集成测试:调用某个接口,自动化的看一下正不正确

单元测试:开发者对单独的函数或模块进行验证

这个命名有严格要求,必须以_test 命名,不然会报错

例子:

/test目录下
print_test.gopackage test
​
import (
    "testing"
)
​
func TestHelloTom(t *testing.T) {
    output := HelloTom()
    expectOutput := "Tom"
    if output != expectOutput {
        t.Errorf("Expected %s do not match actual %s", expectOutput, output)
    }
}
​
print.gopackage test
​
func HelloTom() string {
    return "Jerry"
}
​

在编译器上找到print_test.go文件的TestHelloTom左边运行按键 或 在命令后用go test -v xxx_test.go xxx.go 这样可以两个文件同时编译,不会出现undefined的情况

换一个包,会报另一种形式的错误

如果正确

=== RUN   Test_HelloTom
--- PASS: Test_HelloTom (0.00s)
PASS
或
ok      command-line-arguments  0.561s

单元测试 - 覆盖率

如何衡量代码是否经过了足够的测试?

如何评价项目的测试水平?

如何评估项目是否达到了高水准测试等级?

看覆盖率

JudgeMent_Test文件夹下

judgement.go文件
​
package JudgeMent_Test
​
func JudgePassLine(score int16) bool {
    if score >= 60 {
        return true
    }
    return false
}
judgement_test.go文件
​
package JudgeMent_Test
​
import (
    "github.com/stretchr/testify/assert"
    "testing"
)
​
func TestJudgePassLineTrue(t *testing.T) {
    isPass := JudgePassLine(70)
    assert.Equal(t, true, isPass)
}

终端运行 go test . --cover

输出

ok      test_project/test_project/Day2/JudgeMent_Test   0.324s  coverage: 66.7% of statements

因为只运行了JudgePassLine函数的前两行,函数总共有三行有效代码。2/3=66.7%

现在要让它达到100%

func TestJudgePassLineTrue(t *testing.T) {
    isPass := JudgePassLine(70)
    assert.Equal(t, true, isPass)
}
​
func TestJudgePassLineFalse(t *testing.T) {
    isPass := JudgePassLine(50)
    assert.Equal(t, true, isPass)
}

终端运行 go test . --cover

一般覆盖率:50%-60%,较高覆盖率:80%+。

很难达到100覆盖率%

测试分支相互独立、全面覆盖。

测试单元粒度足够小,函数单一职责。

单元测试 - 文件处理

Mock函数,为一个函数/方法打桩,之后就算文件被修改删了也能运行

用一个函数A,替换函数B。

Patch(target,replacement interface{}) {
    //将函数的地址替换成运行时地址
}
target是原函数,replacement是打桩的函数
​
Unpatch(target interface{}) bool {//测试结束后卸载桩
​
}

Mocktest文件

基准测试

优化代码,需要对当前代码分许

内置的测试框架提供了基准测试的能力

Benchmark 开头

benchmark文件夹

load_balance_selector.gopackage benchmark
​
import (
    "github.com/bytedance/gopkg/lang/fastrand"
    "math/rand"
)
​
var Serverindex [10]intfunc InitServerIndex() {
    for i := 0; i < 10; i++ {
        Serverindex[i] = i + 100
    }
}
​
func SelectServerIndex() int {
    return Serverindex[rand.Intn(10)]
}
​
func SelectFastServerIndex() int {
    return Serverindex[fastrand.Intn(10)]
}
load_balance_selector_test.go
​
package benchmark
​
import "testing"
​
func BenchmarkSelect(b *testing.B) {
    InitServerIndex()
    b.ResetTimer()             //删掉不属于我们测试的损耗
    for i := 0; i < b.N; i++ { //串行的压力测试,也就是基准测试
        SelectServerIndex()
    }
}
​
func BenchmarkSelectServerIndexParallel(b *testing.B) {
    InitServerIndex()
    b.ResetTimer()
    b.RunParallel(func(pb *testing.PB) { //并行的基准测试
        for pb.Next() {
            SelectServerIndex()
        }
    })
}
​
func BenchmarkSelectFastServerIndex(b *testing.B) {
    InitServerIndex()
    b.ResetTimer()
    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            SelectFastServerIndex()
        }
    })
}
​

测试 go test -bench=.