这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
下面相关内容仅供本人回顾使用,如有问题,烦请评论反馈,感激不尽!!!
单元测试的质量某种程度上决定了代码的质量。
单元测试规则
- 所有测试文件以_test.go结尾
- func TestXxx(*testing.T)
- 初始化逻辑放到TestMain中
单元测试——assert
import(
"github.com/stretchr/testify/assert"
"testing"
)
func TestHelloTom(t *testing.T) {
output := HelloTom()
expectOutput := "Tom"
assert.Equal(t, expectOutput, output)
}
func HelloTom() string {
return "Tom"
}
单元测试——测试覆盖率
- 如何衡量代码是否经过了足够的测试
- 如何评价项目的测试水准
- 如何评估项目是否达到了高水准测试等级
func JudgePassLine(score int16) bool {
if score >= 60 {
return true
}
else {
return false
}
}
func TestJudgePassLineTrue(t *testing.T) {
isPass := JudgeePassLine(70)
assert.Equal(t, true, isPass)
}
func TestJudgePassLineFalse(t *testing.T) {
isPass := JudgeePassLine(50)
assert.Equal(t, false, isPass)
}
- 一般覆盖率:
50%~60%,较高覆盖率:80%+ - 测试分支相互独立、全面覆盖
- 测试单元粒度足够小,函数单一职责
单元测试——依赖
- 幂等:重复运行同一个case,结果与之前一致
- 稳定:指单元测试相互隔离,可以独立运行
单元测试——文件处理
如果测试文件被修改了,可能就无法正确测试,这时候就需要Mock。举一个使用Mock来打桩的例子
背景↓
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") // 替换11为00
return destLine
}
func TestProcessFirstLine(t *testing.T) { // 执行单元测试
firstLine := ProcessFirstLine()
assert.Equal(t, "line00", firstLine)
}
monkey: https://github.com/bouk/monkey
这是一个开源的mock测试库,可以对method或者实例的方法进行mock
Monkey Patch的作用域在Runtime,
运行时通过Go的unsafe包能够将内存中函数的地址替换为运行时函数的地址,将待打桩函数或方法的实现跳转。
快速Mock函数:
- 为一个函数打桩
- 为一个方法打桩
// 用函数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的程度;
在实际的项目开发中,经常会遇到代码性能瓶颈,为了定位问题,经常要对代码做性能分;
这时就用到了基准测试,其使用方法与单元测试类似。
- 优化代码,需要对当前代码分析
- 内置的测试框架提供了基准测试的能力