Golang单元测试与覆盖率的实例讲解
作者:pirlo-san 发布时间:2024-05-05 09:27:50
1 概述
C/C++和Java(以及大多数的主流编程语言)都有自己成熟的单元测试框架,前者如Check,后者如JUnit,但这些编程框架本质上仍是第三方产品,为了执行单元测试,我们不得不从头开始搭建测试工程,并且需要依赖于第三方工具才能生成单元测试的覆盖率。
相比之下,Go语言官方则提供了语言级的单元测试支持,即testing包,而且仅通过go工具本身就可以方便地生成覆盖率数据,也就是说,单元测试是Go语言的自带属性,除了好好设计自己的单元测试用例外,开发者不需要操心工程搭建的任何细节。没错,Golang就是这么任性。
2 单元测试
下面我们以《The Go Programming Language》6.5节的比特容器为例,介绍如何通过testing包和go工具集进行单元测试。
2.1 工程目录
不是说好的,Go语言单元测试不需要搭建测试工程么?其实,Golang的测试工程只有一句话:对file.go新建file_test.go文件,并在其中编写测试用例。所以,我们所谓的工程目录其实就是:
$ go env | grep GOPATH
GOPATH="/home/pirlo/go"
$ tree /home/pirlo/go/src/github.com/pirlo-san/let-us-go
/home/pirlo/go/src/github.com/pirlo-san/let-us-go
├── bitvector
│ ├── bitvector.go
│ └── bitvector_test.go
├── LICENSE
└── README.md
/home/pirlo/go是我的GOPATH,其中的github.com/pirlo-san/let-us-go是一个git工程,bitvector则是这个工程下的一个子模块,即比特容器模块,bitvector.go是模块的实现文件,bitvector_test.go则是用于测试比特容器的文件。
2.2 比特容器的实现
Golang没有容器类型,多数容器都是通过map[type]bool实现的,但是通过map实现在某些场景下比较浪费内存,比如容器元素都是一些很小的非负整数的场景:0~31,其实,我们只需要一个uint32类型4个字节就可以了,但是如果采用map[uint32]bool实现,则对每个元素都需要一个uint32的key和bool类型的value。在C/C++语言内,可以很容易地通过位域的方式达到节省内存的目的,那么Golang可不可以采用类似的方式实现呢?当然可以喽。
2.2.1 定义
type IntSet struct {
words []uint
}
const (
wordBitCount = (32 << (^uint(0) >> 63))
)
IntSet是我们定义的比特容器类型,是一个结构体,其中唯一的成员是一个uint类型的切片,想象切片的元素被有序排列成一个“比特”数组,如果容器内存在元素N,则这个数组的第N个元素的值就为1,否则就是0.
wordBitCount用于计算uint类型占用的比特数,这个数字在不同的操作系统或CPU上是不同的。
2.2.2 向容器内添加一个元素
// add x into set s
func (s *IntSet) Add(x int) {
word, index := wordIndex(x)
for word >= len(s.words) {
s.words = append(s.words, 0)
}
s.words[word] |= (1 << index)
}
func wordIndex(x int) (int, uint) {
return x / wordBitCount, uint(x) % wordBitCount
}
先获取这个元素在第几个“word”,以及在这个word内的第几个比特,如果words切片长度不够,则一直添加到可以包含待插入的元素为止,最后将对应元素位置的“比特位”设置为1.
2.2.3 判断某元素是否在容器内
// check wether x is in set s
func (s *IntSet) Has(x int) bool {
word, index := wordIndex(x)
if word >= len(s.words) {
return false
}
return (s.words[word] & (1 << index)) != 0
}
《The Go Programming Language》内还实现了其它接口,包括String,UnionWith等,完整代码见文末链接。
2.3 单元测试用例
来源:https://blog.csdn.net/m0_37554486/article/details/78917471


猜你喜欢
- 前言ThinkPHP出于安全的考虑增加了表单令牌Token,由于通过Ajax异步更新数据仅仅部分页面刷新数据,就导致了令牌Token不能得到
- 1.前期准备1.打开Terminal终端,执行以下命令,将项目所需要的依赖包,都记录到一个文件内备用。pip freeze >requ
- 程序运行效率程序的运行效率分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,而空间效率被称作空间复杂度。时间复杂度主要
- 本文旨在分类讲述执行计划中每一种操作的相关信息。数据访问操作 首先最基本的操作就是访问数据。这既可以通过直接访问表,也可以通过访问索引来进行
- 操作实现函数: 代码如下:Function AddWater(n) Set Photo = 
- (1)服务器配置:[root@localhost ~]# cd /usr/local/src/[root@localhost src]# w
- 分析我们将添加、插入、删除定义为:添加 : 在字符串的后面或者前面添加字符或者字符串插入 : 在字符串之间插入特定字符在Python中,字符
- PHP join() 函数实例把数组元素组合为一个字符串:<?php $arr = array('Hello',
- asyncio的关键字说明event_loop事件循环:程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协
- pandas.DataFrame中的现有列分配给索引index(行名,行标签)。为索引指定唯一的名称很方便,因为使用loc,at选择(提取)
- 使用thinkphp官方的WeChat包,使用不同模式可以成功,但是安全模式就是不行,现将分析解决结果做下记录。分析问题: &nb
- 以发布目录为例:<OBJECT ID="agobjOraSession" RUNAT=&quo
- 1、pip下载安装1.1 pip下载# wget "https://pypi.python.org/packages/source
- 字典类型是Python中最常用的数据类型之一,它是一个键值对的集合,字典通过键来索引,关联到相对的值,理论上它的查询复杂度是 O(1) :&
- 字符串打印打印函数echo: 打印值,用于单值print_r(): 人类可读方式打印,用于数组var_dump():打印结构和类型,一般用于
- 1. 从字典创建DataFrame>>> import pandas>>> dict_a = {'
- 经常上网的人一定碰到过找不到页面的情况,此时是否有点让人沮丧呢,本文介绍了一些404页面设计优秀的例子,当我们撞见些好玩可爱的页面时,有时反
- 本文介绍了如何在Linux下安装MySQL8.0,供大家参考,具体内容如下准备工作:mysql8.0 rpm文件测试工具(比如 idea的d
- 目录一、简介1、优势2、劣势二、安装三、locust的库和方法介绍1、from locust import task2、from locus
- 一般情况下:if(2 > 10){alert("不正确!");} 此比较不会是想要的结果:它相当于2 >1,