这是我参与「第五届青训营 」伴学笔记创作活动的第4天
测试
单元测试
单元测试主要包括输入、测试单元、输出以及校对
优点
- 保证质量:在整体覆盖率足够的情况下,在一定程度上保证了新功能本身的正确性,又未破坏原有代码的正确性
- 提升效率:在代码有bug的情况下,通过编写单元测试,可以在一个叫短周期内定为和修复
规则
- 所有测试文件以_test.go结尾
- 测试方法为
func TestXxx(t *testing.T) - 初始化逻辑放到TestMain中
func HelloTom() string {
return "Jerry"
}
func TestHelloTom(t *testing.T) {
output := HelloTom()
expectOutput := "Tom"
if output ≠ expectOutput {
t.Errorf("Expected %s do not match actual %s",expectOutput,output)
}
}
结果
assert
可以用在测试量大的应用场景
func add(a, b int) int {
return a + b
}
func TestWithAssert(t *testing.T) {
assert.Equal(t, add(1, 2), 3, "Add Error!")
// this will raise an error
assert.Equal(t, add(1, 3), 5, "Add Error!")
}
注意
- 一般覆盖率:50%~60%,较高覆盖率80%+
- 测试分支相互独立、全面覆盖
- 测试单元粒度足够小,函数单一职责
mock
monkey是一个开源的mock测试库,可以对方法或者实例的方法进行mock,反射,指针赋值。Mockey Patch的作用域在Runtime,在运行时通过go的unsafe包能够将内存中函数的地址替换为运行时函数的地址
// 用函数A去替换函数B,B就是原函数,A就是打桩函数
func Patch(target, replacement interface{}) *PatchGuard {
// target就是原函数,replacement就是打桩函数
t := reflect.ValueOf(target)
r := reflect.ValueOf(replacement)
patchValue(t, r)
return &PatchGuard{t, r}
}
func Unpatch(target interface{}) bool {
// 保证了在测试结束之后需要把这个包卸载掉
return unpatchValue(reflect.ValueOf(target))
}
func TestProcessFirstLineWithMock(t *testing.T) {
monkey.Patch(ReadFirstLine, func() string {
return "line110"
})
defer monkey.Unpatch(ReadFirstLine)
line := ProcessFirstLine()
assert.Equal(t, "line000", line)
}
// 通过patch对ReadFirstLine进行打桩mock,默认返回line110,通过defer卸载mock
// 这样整个测试函数就摆脱了本地文件的束缚和依赖
基准测试
基准测试是指测试一段程序的运行性能以及耗费cpu的程度
基准测试以Benchmark开头,入参是testing.B,用b中的N值反复递增循环测试