Go语言工程实践单元测试基准测试示例详解
作者:啵啵肠 发布时间:2024-03-11 17:00:08
背景
测试的出现是为了避免项目中出现重大事故
测试是避免事故的最后一道屏障
测试
单元测试的覆盖率在一定程度上而言,决定了代码的质量
单元测试
通过测试单元的输出与期望值进行校对从而验证代码的正确性,从而保证新旧代码的互不影响与程序的正常运行。
进而单元测试较于编译更易于在较短的周期内发现和定位代码中的错误使损失最小化从而提升效率。所以写单元测试是很有必要的。
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的测试用力
测试单元粒度足够小,函数单一职责
依赖
幂等:重复运行同一个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的程度;
在实际的项目开发中,经常会遇到代码性能瓶颈,为了定位问题,经常要对代码做性能分;
这时就用到了基准测试,其使用方法与单元测试类似。
优化代码,需要对当前代码分析
内置的测试框架提供了基准测试的能力
小结
对于今日课程而言,我将其划分成测试的重要性与分类。 当前课程余下部分为项目实战,该部分内容选择了放置于项目笔记。
来源:https://juejin.cn/post/7190726245607276600


猜你喜欢
- Python 是由吉多·范罗苏姆(Guido Van Rossum)在 90 年代早期设计。 它是如今最常用的编程语言之一。它的语法简洁且优
- 现象:有一个表 action_conf,数据如下:如果想获取以exp_site_10_开头的en_name的记录,sql语句该如何写?&nb
- 在Linux或者Windows下想要查看目录树都可以通过tree命令来实现,两个操作系统中的操作也很相似。使用Linux时,最初以为这是sh
- 本文实例讲述了python网络编程socket实现服务端、客户端操作。分享给大家供大家参考,具体如下:本文内容:socket介绍TCP:服务
- 最近看到一个内部项目的插件加载机制,非常赞。当然这里说的插件并不是指的golang原生的可以在buildmode中加载指定so文件的那种加载
- 可控制的滚动新闻不同于自动的滚动条,它是通过按钮控制移动的,当你把鼠标放在按钮上时,新闻内容就会向上或
- 如何用ASP发送带附件的邮件?请问如何用CDONTS组件发送带附件的邮件? 见下列代码:<%&nb
- Event Handler在HDA中,要创建Python脚本,需要先选择一个事件处理器(EventHandle),他表示你要在什么时候执行你
- vue-cli npm解决vue项目中缺失core-js报错This dependency was not found:core-js/mo
- 最近老婆大人的公司给老婆大人安排了一个根据关键词查询google网站排名的差事。老婆大人的公司是做seo的,查询的关键词及网站特别的多,看着
- 本文实例讲述了python中enumerate函数遍历元素用法。分享给大家供大家参考,具体如下:enumerate函数用于遍历序列中的元素以
- 本文给出一条 SQL 语句用于展示在同一名服务器上,不同的数据库间查询,注意当前连接用户要对两个库都有权限SQL Server 中 SQL
- original article by sp(’Sergio Pereira’) Sergio Pereiralast update: Ma
- 1. 使用函数 np.random.random由于 np.random.random() 默认生成 0~1 之间的小数,因此需要转换一下如
- 一、Tensorlow结构import tensorflow as tfimport numpy as np#创建数据x_data = np
- 当大家发现数据库查询性能很慢的时候,大家都会想到加索引来优化数据库查询性能,但是面对一个复杂的SQL语句,找到一个优化的索引组合对人脑来讲,
- 本文实例讲述了python获得文件创建时间和修改时间的方法。分享给大家供大家参考。具体如下:这里需要用户从控制台输入文件路径import o
- 本文实例讲述了Python redis操作。分享给大家供大家参考,具体如下:一、redisredis是一个key-value存储系统。和Me
- 大家经常用的是Adodb.Stream,但这时就有个缺陷,就是不支持断点续传了。经常看到flashget中是红脸(即不支持断点续传)其实支持
- 一、数据库的建立和销毁建立数据库:create database [if not exists] 数据库名 [default charset