这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天
课堂笔记
本堂课重点内容
- 单元测试
- Mock测试
- 基准测试
详细知识点介绍
##单元测试
流程
输入->测试单元->输出->校对
规则
- 所有测试文件以_test.go结尾
- func TestXxx(*testing.T)
- 初始化逻辑放到TestMain中
案例
package test06
func HelloTom() string {
return "Jerry"
}
package test06
import "testing"
func TestHelloTom(t *testing.T) {
output := HelloTom()
expectOutput := "Tom"
if output != expectOutput {
t.Errorf("Expected: %s, Got: %s", expectOutput, output)
}
}
结果
=== RUN TestHelloTom HelloTom_test.go:9: Expected: Tom, Got: Jerry --- FAIL: TestHelloTom (0.00s)
覆盖率
- 如何衡量代码是否经过了足够的测试?
- 如何评价项目的测试水准?
- 如何评估项目是否达到了高水准测试等级?
计算路过了代码的多少行,比如下面的样例就在代码第二行的位置return了,代码有效行数为3,所以覆盖率为2/3=66.7%
- 可以通过不断改变测试条件,让测试覆盖率较高即可
样例
package test06
func JudgePassLine(socre int16) bool {
if socre >= 60 {
return true
} else {
return false
}
}
package test06
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestJudgePassLineTrue(t *testing.T) {
isPass := JudgePassLine(70)
assert.Equal(t, true, isPass)
}
结果
command-line-arguments 0.237s coverage: 66.7% of statements
重点
- 一般覆盖率:50%-60%;较高覆盖率80%+
- 测试分支相互独立、全面覆盖
- 测试单元粒度足够小,函数单一职责
依赖
单元
- File
- DB
- Cache
Mock
- 幂等
- 稳定(任何函数在任何时间段独立运行)
Mock测试
- 为一个函数打桩
- 为一个方法打桩
优点
不用依赖本地文件
func TestProcessFirstLineWithMock(t *testing.T) {
monkey.Patch(ReadFirstLine, func() string {
return "line110"
})
defer monkey.Unpatch(ReadFirstLine)
line := ProcessFirstLine()
assert.Equal(t, "line000", line)
}
基准测试
优化代码,需要对当前代码分析
内置的测试框架提供了基准测试的能力
- 使用了第三方SDK
- 降低了并发的性能
实践练习例子
基准测试
package test06
import (
"math/rand"
"testing"
)
var ServerIndex [10]int
func InitServerIndex() {
for i := 0; i < 10; i++ {
ServerIndex[i] = i + 100
}
}
func Select() int {
return ServerIndex[rand.Intn(10)]
}
func BenchmarkSelect(b *testing.B) {
InitServerIndex()
b.ResetTimer()
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()
}
})
}
文件处理
下文普通测试时是没有问题的,但是一旦测试文件(“log”)被修改,就会出错
package test06
import (
"bufio"
"os"
"strings"
)
func ReadFirstLine() string {
open, err := os.Open("log")
defer open.Close()
if err != nil {
return ""
}
scanner := bufio.NewScanner(open)
for scanner.Scan() {
return scanner.Text()
}
return ""
}
func ProcessFirstLine() string {
line := ReadFirstLine()
destLine := strings.ReplaceAll(line, "11", "00")
return destLine
}
package test06
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestReadFirstLine(t *testing.T) {
firstLine := ProcessFirstLine()
assert.Equal(t, "line00", firstLine)
}
课后个人总结
- 单元测试简单,但是需要将覆盖率提高来保证全部函数的覆盖
- Mock测试需要引入第三方包,不会自动引入