Golang单元测试中的技巧分享

 更新时间:2023年03月13日 10:04:59   作者:LinkinStar  
这篇文章主要为大家详细介绍了Golang进行单元测试时的一些技巧和科技,文中的示例代码讲解详细,具有一定的参考价值,感兴趣的小伙伴可以了解一下

打桩测试

当我们在编写单元测试的时候,有时我们非常想 mock 掉其中一个方法,但是这个方法又没有接口去定义和实现(无法用 github.com/golang/mock 来实现),这时就可以尝试看看我们的打桩黑科技。

代码

这里我们使用 github.com/agiledragon/gomonkey 来实现。

实际中,经常在代码中会遇到一些随机值的情况,比如验证码。为了方便测试,我们会想要 mock 掉随机值方法,让每次产生的值固定方便后续的测试。

package main

import (
  "fmt"
  "testing"

  "github.com/agiledragon/gomonkey/v2"
  "go-demo/m/unit-test/other/rand"
)

func init() {
  gomonkey.ApplyFunc(rand.Number, func() int { return 666 })
}

func TestRand(t *testing.T) {
  fmt.Println(rand.Number())
}

其中 rand.Number() 是我们在另一个包中实现的方法。我们使用 gomonkey.ApplyFunc 相当于直接替换了原有方法的实现,强制返回了 mock 的数据 666。

注意事项

  • 使用 gomonkey 时,注意一定要使用 -gcflags=all=-l 来禁止内联优化,否则容易导致打桩不生效。如:go test -gcflags=all=-l -v
  • 在 Mac 的 M1 下打桩不生效,可以使用环境变量 GOARCH=amd64 来进行测试,只不过这样就无法进行断点调试。https://github.com/agiledragon/gomonkey/issues/77
  • 毕竟是黑科技,实际使用环境对于测试还是有影响的。

压测

这里的压测通常不是对接口的压测,而是对于某些方法的压测。Golang 提供 非常好用的 b *testing.B 来专门进行压测。

代码

非常容易上手,让我们直接来看代码

var numbers = []int{
  100,
  1000,
  77777,
  666666,
}

func BenchmarkPrimeNumbers(b *testing.B) {
  for _, v := range numbers {
    b.Run(fmt.Sprintf("calc_num_%d", v), func(b *testing.B) {
      for i := 0; i < b.N; i++ {
        primeNumbers(v)
      }
    })
  }
}

使用

使用 -bench=. 即可

➜ go test -bench=. b_test.go
goos: darwin
goarch: arm64
BenchmarkPrimeNumbers/calc_num_100-8             3391329               348.9 ns/op
BenchmarkPrimeNumbers/calc_num_1000-8             293733              3979 ns/op
BenchmarkPrimeNumbers/calc_num_77777-8               730           1619089 ns/op
BenchmarkPrimeNumbers/calc_num_666666-8               42          28509805 ns/op
PASS
ok      command-line-arguments  5.846s

可以看到次数和耗时,这样的数据经常会被贴在开源项目README的性能比较板块中。

测试覆盖率

单元测试当然少不了覆盖率咯,看着高高的覆盖率才有成就感对不对?

我们可以使用 -cover 参数来统计单元测试的代码覆盖率

➜ go test -cover .           
ok      go-demo/m/unit-test/service     0.879s  coverage: 70.0% of statements

还可以生成 profile 然后通过可视化网页查看分析

➜ go test ./... -coverprofile=cover.out
ok      go-demo/m/unit-test/service     0.108s  coverage: 70.0% of statements
➜ go tool cover -html=cover.out

当然,如果你和我一样使用 goland 进行开发,可以直接在界面上点击单元测试,就可以快速进行覆盖率测试,并且展示也很方便,很快能看到有哪些代码没有被测试覆盖。

表格驱动测试

TDT 的提出也算是给单元测试提供了一条不错的思路。主要的形式就是将测试的数据做成类似表格,然后测试的时候遍历所有的数据来进行测试,测试代码不动,只需要增加测试数据就可以了。go 很多官方库用了这样的写法来做测试。

package main

import (
    "testing"
)

func TestAdd(t *testing.T) {
    tests := []struct {
        a, b, expected int
    }{
        {1, 2, 3},
        {0, 0, 0},
        {-1, 1, 0},
        {-1, -1, -2},
    }

    for _, test := range tests {
        result := Add(test.a, test.b)
        if result != test.expected {
            t.Errorf("Add(%d, %d) = %d; expected %d", test.a, test.b, result, test.expected)
        }
    }
}

func Add(a, b int) int {
    return a + b
}

我们可以通过 github.com/cweill/gotests 来帮助我们快速生成想要的表格驱动测试代码

到此这篇关于Golang单元测试中的技巧分享的文章就介绍到这了,更多相关Golang单元测试内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • GO语言实现批量压缩图片和水印

    GO语言实现批量压缩图片和水印

    这篇文章主要介绍了GO语言实现批量压缩图片和水印,主要用到了github.com/nfnt/resize这个第三方库,仅仅支持JPG图片格式,有相同需求的小伙伴参考下吧。
    2015-03-03
  • Golang分布式锁详细介绍

    Golang分布式锁详细介绍

    分布式锁是控制分布式系统之间同步访问共享资源的一种方式。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源时,需要通过一些互斥手段来防止彼此之间的干扰以保证一致性,在这种情况下,就需要使用分布式锁了
    2022-10-10
  • 浅析Go中序列化与反序列化的基本使用

    浅析Go中序列化与反序列化的基本使用

    序列化是指将对象转换成字节流,从而存储对象或将对象传输到内存、数据库或文件的过程,反向过程称为“反序列化”。本文主要介绍了Go中序列化与反序列化的基本使用,需要的可以参考一下
    2023-04-04
  • 使用Go重试机制代码更可靠

    使用Go重试机制代码更可靠

    这篇文章主要为大家介绍了使用Go重试机制的使用,使你的代码更加可靠,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Go Web编程添加服务器错误和访问日志

    Go Web编程添加服务器错误和访问日志

    这篇文章主要为大家介绍了Go Web编程添加服务器错误日志和访问日志的示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • go gin 正确读取http response body内容并多次使用详解

    go gin 正确读取http response body内容并多次使用详解

    这篇文章主要为大家介绍了go gin 正确读取http response body内容并多次使用解决思路,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Go有效获取变量类型多种方法探索

    Go有效获取变量类型多种方法探索

    这篇文章主要介绍了Go有效获取变量类型的多种方法探索,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-02-02
  • golang中validator包的使用教程

    golang中validator包的使用教程

    Validator 实际上是一个验证工具,属于 golang 的第三方包,这个包中使用了各种反射技巧来提供了各种校验和约束数据的方式方法,下面就跟随小编一起来学习一下validator包的使用吧
    2023-09-09
  • Golang自定义结构体转map的操作

    Golang自定义结构体转map的操作

    这篇文章主要介绍了Golang自定义结构体转map的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Go框架三件套Gorm Kitex Hertz基本用法与常见API讲解

    Go框架三件套Gorm Kitex Hertz基本用法与常见API讲解

    这篇文章主要为大家介绍了Go框架三件套Gorm Kitex Hertz的基本用法与常见API讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪<BR>
    2023-02-02

最新评论