测试| 青训营笔记

90 阅读2分钟

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

测试

单元测试

单元测试主要包括输入、测试单元、输出以及校对

优点

  1. 保证质量:在整体覆盖率足够的情况下,在一定程度上保证了新功能本身的正确性,又未破坏原有代码的正确性
  2. 提升效率:在代码有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)
    }
}

结果

image-20230121155400359.png 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值反复递增循环测试