返回顶部
首页 > 资讯 > 后端开发 > GO >Go 语言进阶单元测试示例详解
  • 334
分享到

Go 语言进阶单元测试示例详解

Go 语言单元测试Go 单元测试 2023-01-28 12:01:05 334人浏览 独家记忆
摘要

目录前言测试单元测试规则示例assert覆盖率依赖Mock基准测试前言 本文从单元测试实践角度出发,提升对代码质量的意识。 本文内容主要包括:单元测试、Mock测试、基准测试。 测

前言

本文从单元测试实践角度出发,提升对代码质量的意识。

本文内容主要包括:单元测试、Mock测试、基准测试。

测试

测试可以提高代码的质量、减少事故的发生。

测试又分为:回归测试、集成测试、单元测试。

回归测试是指对QA手动回归一些特定场景,可以理解为我们说的手动点点。

集成测试是指对系统功能维度做验证,比如对服务暴露的接口验证,一般是自动化的验证。

单元测试是指在开发阶段,开发者对单独的函数、模块做验证,写一些测试用例。

单元测试

单元测试组成部分:输入、输出、测试单元、与期望的校对,测试单元又包括函数、接口、模块、复杂的聚合函数等。

通过单元测试的输出再与期望输出进行校对,来验证代码的正确性。通过单元测试可以保证代码的质量,也可以在一定程度上提升效率,比如通过运行单元测试可以快速定位到有问题的代码。

规则

单元测试的编写有一定的规则:

  • 所有测试文件以 _test.Go 结尾
  • 测试方法名以Test开头,参数要用testing func TestXxx(t *testing.T)
  • 测试初始化逻辑放到TestMain
  • 通过go test命令进行测试

示例

import "testing"
func TestHelloTom(t *testing.T) {
    output := HelloTom()
    expectOutPut := "Tom"
    if output != expectOutPut {
        t.Errorf("Expected %s do not match actual %s", expectOutPut, output)
    }
}
func HelloTom() string {
    return "Jerry"
}

通过go test命令运行得到以下结果,从测试结果里可以看出,我们期望得到的是Tom,但实际得到的却是Jerry

--- FAIL: TestHelloTom (0.00s)
helloTom_test.go:9: Expected Tom do not match actual Jerry
FAIL
exit status 1
FAIL    learning/mytesting      0.496s

assert

另外我们可以使用开源assert包,来代替我们自己的if判断。

func TestHelloTom(t *testing.T) {
    output := HelloTom()
    expectOutPut := "Tom"
    assert.Equal(t, expectOutPut, output)
}

再次通过go test命令运行得到以下结果,输出了更详细的堆栈信息。

覆盖率

如何评估单元测试呢?是通过代码覆盖率来评估的,评估的标准包括:

  • 衡量代码是否经过了足够的测试
  • 评价项目的测试水准
  • 评估项目是否达到了高水平的测试等级

下面通过一个例子来看下代码覆盖率:

// judgepass.go
func JudgePassLine(score int16) bool {
    if score >= 16 {
        return true
    }
    return false
}
// judgepass_test.go
func TestJudgePassLineTrue(t *testing.T) {
    isPass := JudgePassLine(70)
    assert.Equal(t, true, isPass)
}

通过命令来看覆盖率go test judgepass_test.go judgepass.go --cover

输出结果为:

ok  command-line-arguments  0.327s  coverage: 66.7% of statements

可以看到,提示出的代码覆盖率为66.7%,因为只走了一个if分支。如果要想达到100%的代码覆盖率的话,就要把所有的分支都要覆盖到。

一般的覆盖率为50%~60%,较高的覆盖率要达到80%+。要注意:测试分支相互独立、要全面覆盖,测试单元粒度要足够小,满足函数单一职责。

依赖

一个实际项目不可能只是一个简单的单体函数,肯定会很复杂,存在其他的依赖,比如依赖数据库Redis、文件等外部依赖。

单元测试一般有两个目标:幂等、稳定。

幂等:重复执行一个用例、调用一个接口,返回的结果是一样的。

稳定:单元测试是相互隔离的,在任何时间都能独立运行。

Mock

如果单元测试用到数据库、redis等,在单元测试里直接连接会涉及到网络传输,这是不稳定的,所以要用到Mock机制。

开源Mock框架GitHub.com/bouk/monkey

这个Mock包可以对函数或方法进行打桩,打桩就是用一个函数A来替换一个函数B。

monkey的实现原理主要是在运行时,通过Gounsafe包能够将内存中函数的地址替换为运行时函数的地址,最终调用的是打桩函数,从而实现Mock的功能。

Mock常用方法:PatchUnpatch

Patch方法有两个参数,target为替换的函数(原函数),replacement为要替换成的函数。

func Patch(target, replacement interface{}) *PatchGuard {
    t := reflect.ValueOf(target)
    r := reflect.ValueOf(replacement)
    patchValue(t, r)
    return &PatchGuard{t, r}
}

Unpatch为测试结束之后,要把打的桩给卸载掉。

func Unpatch(target interface{}) bool {
    return unpatchValue(reflect.ValueOf(target))
}

下面通过Mock来模拟对文件的操作。

func TestProcessFirstLineWithMock(t *testing.T) {
    monkey.Patch(ReadFirstLine, func() string {
        return "line110"
    })
    defer monkey.Unpatch(ReadFirstLine)
    line := ProcessFirstLine()
    assert.Equal(t, "line000", line)
}
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
}

该测试用例对ProcessFirstLine函数进行测试,这个函数调用了ReadFirstLine函数,涉及到文件的操作,通过Mock对文件的操作进行打桩,这样就避免了其他进程对文件操作的影响。

基准测试

Go还提供了基准测试框架,可以测试一段程序的性能、CPU消耗,可以对代码做性能分析,测试方法与单元测试类似。

基准测试规则:

  • 基准测试以Benchmark为前缀
  • 需要一个*testing.B类型的参数b
  • 基准测试必须要执行b.N次

下面通过一个模拟负载均衡的例子,来看下基准测试:

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()
        }
    })
}

通过命令 go test -bench=. 运行测试,输出结果如下:

goos: darwin
goarch: amd64
pkg: learning/bench
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.70GHz
BenchmarkSelect-8               50264580               23.47 ns/op
BenchmarkSelectParallel-8       13717840               133.4 ns/op
PASS
ok      learning/bench  4.559s

BenchmarkSelect-8 表示对Select函数进行基准测试,数字8表示 GOMAXPROCS 的值。

23.47 ns/op 表示每次调用Select函数耗时23.47ns

50264580 这是50264580次调用的平均值。

字节开源的go框架:github.com/bytedance/g…

引用 Go 语言进阶与依赖管理

以上就是Go 语言进阶单元测试示例详解的详细内容,更多关于Go 语言单元测试的资料请关注编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: Go 语言进阶单元测试示例详解

本文链接: https://lsjlt.com/news/178499.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Go 语言进阶单元测试示例详解
    目录前言测试单元测试规则示例assert覆盖率依赖Mock基准测试前言 本文从单元测试实践角度出发,提升对代码质量的意识。 本文内容主要包括:单元测试、Mock测试、基准测试。 测...
    99+
    2023-01-28
    Go 语言单元测试 Go 单元测试
  • Go语言基础单元测试与性能测试示例详解
    目录概述单元测试代码说明如下问题注意性能测试基本使用自定义测试时间概述 测试不是Go语言独有的,其实在很多语言都有测试,例如:Go、Java、Python… 要想成为一名合格的大牛,...
    99+
    2024-04-02
  • Go语言工程实践单元测试基准测试示例详解
    目录背景测试单元测试演示覆盖率依赖文件处理Mock基准测试小结背景 测试的出现是为了避免项目中出现重大事故 测试是避免事故的最后一道屏障 测试 单元测试的覆盖率在一定程度上而言,...
    99+
    2023-02-05
    Go语言单元测试基准测试 Go语言测试
  • Go语言单元测试的示例分析
    小编给大家分享一下Go语言单元测试的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、单元测试分类及其概念1.基本分类测试函数 函数前缀为Test 主要用...
    99+
    2023-06-29
  • Go语言单元测试与性能测试示例分析
    这篇文章主要讲解了“Go语言单元测试与性能测试示例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Go语言单元测试与性能测试示例分析”吧!概述测试不是Go语言独有的,其实在很多语言都有测试...
    99+
    2023-06-25
  • C语言实现单元测试的示例详解
    目录前沿使用前提测试框架如下测试方法编写文件验证前沿 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际...
    99+
    2024-04-02
  • Go 语言单元测试
    php小编鱼仔今天为大家介绍一下Go语言的单元测试。在软件开发中,单元测试是非常重要的一环。通过编写测试用例,我们可以验证代码的正确性,提高代码质量和可维护性。Go语言提供了丰富的测试...
    99+
    2024-02-09
    go语言
  • Go语言单元测试超详细解析
    目录一、单元测试分类及其概念1.基本分类2.细说单元测试分类二、结合代码细说每一种测试1.基准测试2.组测试与子测试三、pprof调试工具1.对主函数进行传参2.pprof性能调优前...
    99+
    2024-04-02
  • Go单元测试利器testify使用示例详解
    目录testifyassert 包require 包mock 包suite 包testify 在团队里推行单元测试的时候,有一个反对的意见是:写单元测试耗时太多。且不论这个意见对错...
    99+
    2022-12-15
    Go 单元测试testify Go testify
  • Go语言单元测试和基准测试实例代码分析
    本篇内容主要讲解“Go语言单元测试和基准测试实例代码分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Go语言单元测试和基准测试实例代码分析”吧!背景测试的出现是为了避免项目中出现重大事故测试是...
    99+
    2023-07-05
  • 一文详解Go语言单元测试的原理与使用
    目录前言为什么要引用单元测试类单元测试基本介绍优点Testing规范基本使用Golang运行命令行案例前言 为什么要引用单元测试类 传统方法的缺点分析 不方便,我们需要在main函数...
    99+
    2024-04-02
  • Go语言单例模式示例详解
    目录简单单例模式加锁的单例模式双check 的单例模式sync.Once 的单例模式简单单例模式 单例模式是创建类型的模式,它是为了保证执行期间内只有一个实例。使用 Golang 指...
    99+
    2024-04-02
  • Go单元测试对GORM进行Mock测试
    目录前言项目准备初始化测试工作对Create进行Mock测试Get 操作的Mock测试Update 操作的Mock测试总结前言 在 Go 单元测试这个系列的第二部分 数据库...
    99+
    2024-04-02
  • 一文带你了解Go语言中的单元测试
    目录基本概念示例一:取整函数基本测试示例二:Fail()函数示例三:FailNow函数实例四:Log和Fetal函数基本概念 上一节提到,代码完成的标准之一还包含了单元测试,这部分也...
    99+
    2024-04-02
  • Go语言中的性能测试与单元测试的区别
    性能测试评估应用程序在不同负载下的性能,而单元测试验证单个代码单元的正确性。性能测试侧重于测量响应时间和吞吐量,而单元测试关注函数输出和代码覆盖率。性能测试通过高负载和并发模拟实际环境,...
    99+
    2024-05-08
    单元测试 性能测试 go语言
  • Golang 单元测试和基准测试实例详解
    目录前言Go 单元测试单元测试覆盖率基准测试前言 多人协作的项目里,要保证代码的质量,自然离不开单元测试。开发完一个功能后肯定要对所写的代码进行测试,测试没有问题之后再合并到代码库供...
    99+
    2024-04-02
  • C语言进阶栈帧示例详解教程
    目录正片开始栈有什么用?寄存器main函数创建局部变量创建函数部分形参与实参正片开始 今天来讲讲我对栈帧创建与销毁的拙见。理解什么是栈帧首先知道什么是栈: 在数据结构中, 栈是限定仅...
    99+
    2024-04-02
  • 前端自动化测试Vue中TDD和单元测试示例详解
    目录1、简单用例入门2、快照测试3、覆盖率测试4、结合 Vuex 进行测试1、简单用例入门 Vue 提供了 @vue/test-utils 来帮助我们进行单元测试,创建 Vue 项...
    99+
    2023-02-14
    Vue TDD单元测试 Vue 前端自动化测试
  • Junit 单元测试(详解)
    Junit 单元测试 前言一、概述1. JUnit 基本概念2. JUnit 特点和用法3. 如何编写和运行单元测试 二、安装和配置 Junit三、编写和运行 Junit 测试四、运行和调试 Junit 测试五、使用 Junit...
    99+
    2023-08-21
    junit 单元测试 java
  • Go单元测试对数据库CRUD进行Mock测试
    目录前言go-sqlmock安装使用示例miniredis安装使用示例总结前言 最近在实践中也总结了一些如何用表格驱动的方式使用 gock Mock测试外部接口调用。以及怎么对GOR...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作