温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Go语言单元测试和基准测试实例代码分析

发布时间:2023-02-07 09:26:28 来源:亿速云 阅读:114 作者:iii 栏目:开发技术

本篇内容主要讲解“Go语言单元测试和基准测试实例代码分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Go语言单元测试和基准测试实例代码分析”吧!

    背景

    测试的出现是为了避免项目中出现重大事故

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

    测试

    单元测试的覆盖率在一定程度上而言,决定了代码的质量

    单元测试

    Go语言单元测试和基准测试实例代码分析

    通过测试单元的输出与期望值进行校对从而验证代码的正确性,从而保证新旧代码的互不影响与程序的正常运行。

    进而单元测试较于编译更易于在较短的周期内发现和定位代码中的错误使损失最小化从而提升效率。所以写单元测试是很有必要的。

    Golang单元测试对文件名和方法名,参数都有很严格的要求

    • 文件名必须以xx_test.go命名

    • 方法必须是Test[^a-z]开头

    • 方法参数必须t *testing.T

    • 初始化逻辑放到TestMain中

    • 使用go test执行单元测试

    演示

    通过第三方包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"
    }

    覆盖率

    覆盖率出现的目的:

    • 衡量代码是否经过了足够的测试

    • 评价项目的测试水准

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

    通过go test命令测试函数的覆盖率

    // judgment.go
    func JudgePassLine(score int16) bool {
        if score >= 60 {
            return true
        }
        else {
            return false
        }
    }
    // judgment_test.go
    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)
    }
    /*
     通过go test 命令测试覆盖率
     go test judgment_test.go judgment.go --cover
    */

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

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

    对于上述案例代码而言

    应出现成绩大于等于60 和小于60的测试用力

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

    依赖

    Go语言单元测试和基准测试实例代码分析

    • 幂等:重复运行同一个case,结果与之前一致

    • 稳定:指单元测试相互隔离,可以独立运行

    文件处理

    当测试文件被修改后,可能会导致测试失败或错误率增高

    从而出现了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)
    }

    Mock

    monkey: 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的程度;

    在实际的项目开发中,经常会遇到代码性能瓶颈,为了定位问题,经常要对代码做性能分;

    这时就用到了基准测试,其使用方法与单元测试类似。

    • 优化代码,需要对当前代码分析

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

    到此,相信大家对“Go语言单元测试和基准测试实例代码分析”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    go
    AI