Go语言测试——【单元测试 | Mock测试 | 基准测试】

news2024/11/26 19:23:30

在这里插入图片描述

作者:非妃是公主
专栏:《Golang》
博客主页:https://blog.csdn.net/myf_666
个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩
在这里插入图片描述

文章目录

  • 一、单元测试
    • 1. 测试文件命名
    • 2. 测试函数
    • 3. 测试覆盖率
    • 4. Tips
  • 二、Mock测试
  • 三、基准测试
    • 1. 性能劣化
    • 2. 原因分析
    • 3. 性能优化
    • 4. 一个小疑问?
  • the end……

软件测试:软件测试(英语:Software Testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。换句话说,软件测试是一种实际输出与预期输出之间的审核或者比较过程。软件测试的经典定义是:在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其是否能满足设计要求进行评估的过程。

软件测试的概念大家都很熟悉,他是为了发现程序中的错误,但永远也无法证明软件没有错误。

同时,软件测试按照测试策略可以分为单元测试集成测试回归测试等。按照测试用例的编写方法,又可以分成黑盒测试白盒测试等。

单元测试,是测试中成本最低,也最容易发现bug的一个缓解。对于不同的编程语言,一般有着不同的单元测试框架!就Go语言而言,有3个方面的测试——单元测试、Mock测试、基准测试。


一、单元测试

1. 测试文件命名

所有测试文件以_test结尾,如下图:
在这里插入图片描述


2. 测试函数

测试函数名字,为TestXxx,其中为函数名前加上Test,print.go示例如下:

package test

func HelloTom() string {
	return "非妃是公主"
}

print_test.go示例如下:

package test

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

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

运行测试程序,测试输出如下:

在这里插入图片描述

修改函数返回为Tom后输出正常,如下:

在这里插入图片描述

值得注意的是,由于一些复杂的测试用例,需要在测试前进行初始化,这可以放在TestMain函数中进行定义,完成前置释放操作。

在这里插入图片描述


3. 测试覆盖率

如下运行后,可以在控制台看到测试覆盖率,具体操作如下:
在这里插入图片描述

从这里可以看到测试覆盖率情况,如下:

在这里插入图片描述


4. Tips

  • 一般测试覆盖率应该在50%~60%,较高覆盖率80%+。
  • 测试分支相互独立,全面覆盖。
  • 测试粒度足够小,函数单一职责。

二、Mock测试

Mock也叫做打桩,它的作用是可以降低程序不同模块之间的耦合度。比如,正常我们需要从一个文件中读取数据,然后再进行数据处理模块的测试,但是由于读取数据这部分也是存在代码的,也可能出现异常、错误。

如果最终测试没有通过,就存在两种可能:

  1. 文件读取存在问题;
  2. 数据处理存在问题。

为了使得出现错误的可能性更为单一,便于问题的定位。

我们就可以通过mock,将这部分的代码替换掉,生成虚拟数据,这时候,输入到数据处理函数中,这样就可以实现对数据处理模块的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")
	return destLine
}

我们要对处理函数进行测试,但是处理函数中是依赖一个ReadFirstLine这个函数的,常规的单元测试如下:

func TestProcessFirstLine(t *testing.T) {
	firstLine := ProcessFirstLine()
	assert.Equal(t, "line00", firstLine)
}

从上面可以看出,常规的单元测试就是正常调用ProcessFirstLine函数,因此需要调用ReadFirstLine里面的函数,会造成错误定位不精确的问题。

因此就需要将其返回值Mock,如下:

func TestProcessFirstLineWithMock(t *testing.T) {
	monkey.Patch(ReadFirstLine, func() string {
		return "line110"
	})
	defer monkey.Unpatch(ReadFirstLine)
	line := ProcessFirstLine()
	assert.Equal(t, "line000", line)
}

需要用到的库,如下:

import (
	"bou.ke/monkey"
	"github.com/stretchr/testify/assert"
	"testing"
)

这里的monkey是一个mock相关的库,通过它的patch函数,即可实现打桩,进而不再依赖本地文件。


三、基准测试

首先来看一下什么是基准测试,百度百科定义如下:

基准测试是指通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试。例如,对计算机CPU进行浮点运算、数据访问的带宽和延迟等指标的基准测试,可以使用户清楚地了解每一款CPU的运算性能及作业吞吐能力是否满足应用程序的要求。1

下面来看一个负载均衡的例子,首先有10个服务器,每次选择一个服务器进行执行,代码如下:

import (
	"github.com/bytedance/gopkg/lang/fastrand"
	"math/rand"
)

var ServerIndex [10]int

func InitServerIndex() {
	for i := 0; i < 10; i++ {
		ServerIndex[i] = i+100
	}
}

func Select() int {
	return ServerIndex[rand.Intn(10)]
}

其中,initServerIndex是初始化服务器函数,Select即为随机选择一个服务器实现负载均衡。

基准测试函数命名以Benchmark开头,输入参数是testing.B,用b中的N值(即:b.N)反复递增循环测试。(如果Select的运行时间小于1s,那么N值将按照1、2、5、10、20、50……递增,直到递增到运行时间超过1s为止,然后去计算平均时间;如果超过1s,那么N就为1。)

这样处理的好处就是,可以使得求解得到的时间更加准确,不会收到机器运行状态的影响。

代码如下:

func BenchmarkSelect(b *testing.B) {
	InitServerIndex()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		Select()
	}
}

其中,ResetTimer()为重置计时器,再Select操作前进行充值,可以使得时间检测更加准确。

以Parallel结尾标识多协程并发测试,测试代码如下:

func BenchmarkSelectParallel(b *testing.B) {
	InitServerIndex()
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			Select()
		}
	})
}

1. 性能劣化

运行后发现,在并发情况下,代码性能存在一定的劣化。

在这里插入图片描述


2. 原因分析

分析原因,是由于rand为了保证全局的随机性和并发安全,持有了一把全局锁,进而影响了性能。


3. 性能优化

由于字节跳动公司后端主要采用Go语言,因此为了解决这一问题,字节跳动公司开源了一个高性能随机数方法 fastrand,开源地址为:https://github.com/bytedance/gopkg.

fastrand优化后的负载均衡代码如下:

import (
	"github.com/bytedance/gopkg/lang/fastrand"
)

func FastSelect() int {
	return ServerIndex[fastrand.Intn(10)]
}

在这里插入图片描述

从上图可以看出,无论是并发还是串行运行,FastSelect效率都比Select高。


4. 一个小疑问?

这里有一个疑问,知道的读者可以评论区回答一下。为什么串行的FastSelect运行时间是3.467ns,而并行的是0.5309ns呢?

这里我提出一种猜测,产生这种原因,可能和Timer的计时方法有关!比如利用如下公示:

E f f i c i e n c y = R u n T i m e N u m O p e r a t i o n s Efficiency=\frac{RunTime}{NumOperations} Efficiency=NumOperationsRunTime

其中,Efficiency用的就是ns/op作为单位,数值越小,表示消耗的时间越小,效率也就越高!RunTime单位为nsNumOperations指在这段时间内执行的操作数。

这样我们就可以解释问什么并行操作的效率更高了,因为我们在RunTime这段时间内有多个操作在并行执行,也就是分母会很大,这样效率也就会更高了。

总结一下,不难发现,基准测试主要是对程序的某一性能指标进行可对比的测试,然后点对点的进行性能的优化,因此更具有针对性


the end……

Go语言测试——单元测试、Mock测试、基准测试三部分的内容到这里就要结束啦~~

到此既是缘分,欢迎您的点赞评论收藏关注我,不迷路,我们下期再见!!

😘😘😘 我是Cherries,一位计算机科班在校大学生,写博客用来记录自己平时的所思所想!
💞💞💞 内容繁杂,又才疏学浅,难免存在错误,欢迎各位大佬的批评指正!
👋👋👋 我们相互交流,共同进步!

:本文由非妃是公主发布于https://blog.csdn.net/myf_666,转载请务必标明原文链接:https://blog.csdn.net/myf_666/article/details/128938363


  1. 百度百科——基准测试 ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/471495.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux脚本篇】什么是shell脚本,什么是shell变量

目录 &#x1f341;什么是shell &#x1f342;什么是shell脚本 &#x1f342;shell脚本能做什么 &#x1f342;学习shell需要哪些知识 &#x1f342;shell基本规范 &#x1f342;shell脚本五种运行方式 &#x1f341;shell变量 &#x1f342;变量命名规范 &#x1f342;shell变…

配置 RT-Thread 的工程目录

1. 前言 RT-Thread 基于 Scons 的包管理非常方便让我们使用 RT-Thread 进行开发&#xff0c;但在实际工程中将应用代码写到 RT-Thread 官方提供的 bsp 目录下面会非常不便于使用&#xff0c;无法使用自己 git 工具进行代码管理。 解决方式&#xff0c;可以是 fork 出一个基于特…

Python 依赖库管理:pipreqs、pigar、pip-tools、pipdeptree

在 Python 的项目中&#xff0c;如何管理所用的全部依赖库呢&#xff1f;最主流的做法是维护一份“requirements.txt”&#xff0c;记录下依赖库的名字及其版本号。 那么&#xff0c;如何来生成这份文件呢&#xff1f;一种常规的方法&#xff1a; pip freeze > requiremen…

从零开始学习Web自动化测试:如何使用Selenium和Python提高效率?

B站首推&#xff01;2023最详细自动化测试合集&#xff0c;小白皆可掌握&#xff0c;让测试变得简单、快捷、可靠https://www.bilibili.com/video/BV1ua4y1V7Db 目录 引言&#xff1a; 一、了解Web自动化测试的基本概念 二、选择Web自动化测试工具 三、学习Web自动化测试的…

企业数据挖掘平台|道路运输安全大数据分析解决方案

TipDM大数据挖掘建模平台是由泰迪智能科技自主研发打造的可视化、一站式、高性能的数据挖掘与人工智能建模服务平台。目前已与民政、广电、电力、交通运输等多个行业的100客户达成及合作。 基于数据挖掘平台的道路运输安全大数据分析解决方案如下&#xff1a; 方案背景 …

U盘数据加密怎么设置?这个方法更快速、更安全!

U盘是目前使用率最高的移动储存设备&#xff0c;有时我们需要使用U盘存放非常重要的数据&#xff0c;那么就需要将其进行加密。常见的加密手段&#xff0c;如BitLocke驱动器加密&#xff0c;它的加密速度非常慢&#xff0c;当U盘中的数据稍微多一点的时候&#xff0c;我们就需要…

分不清信息化、数字化的区别?这篇文章让你全明白

前几天看到一篇讲数字化的文章&#xff0c;把信息化和数字化混为一谈&#xff0c;一些企业在实践转型的时候也分不清数字化和信息化之间的区别。 正好借这个问题尝试梳理一下数字化和信息化之间的本质区别。个人拙见&#xff0c;也欢迎大家评论区探讨。 01 业务侧重点不同 信…

上传了ipa但iTunes Connect没有构建版本问题

上传了ipa但iTunes Connect没有构建版本问题 转载&#xff1a;上传了ipa但iTunes Connect没有构建版本问题 AU上传ipa出现下图红框提示说明成功上传&#xff0c;如果App Store后台没有出现构建版本&#xff0c;请登录 apple账号对应的邮箱查看反馈&#xff0c;特别留意垃圾邮…

三角函数在js中的应用与二维空间绕另一个点旋转计算应用

开发中遇到一个问题&#xff0c;二维空间里正方形&#xff0c;按p点旋转90度后的点A2点的坐标是多少&#xff0c;这个设计到三角函数和矩阵的运算下面有公式。 由此翻了一遍三角函数相关的知识&#xff1a; A点绕p点旋转90度得A2点的坐标是多少&#xff0c;用三角函数解答&…

Java开发 - 不知道算不算详细的JUC详解

前言 大概有快两周没有发文了&#xff0c;这段时间不断的充实自己&#xff0c;算算时间&#xff0c;也到了该收获的时候&#xff0c;今天带来一篇JUC详解&#xff0c;但说实话&#xff0c;我也不敢自信它详不详细。JUC说白了就是多线程&#xff0c;学Java不久的人知道多线程&a…

openSUSE----openSUSE常用的软件包管理命令

【原文链接】openSUSE----openSUSE常用的软件包管理命令 zypper 是openSUSE操作系统软件包管理命令 repos源管理常用命令 zypper repos (或zypper lr&#xff09; 列出所有定义的安装源zypper addrepo &#xff08;或zypper ar) 添加一个新的安装源zypper removerepo (或zyp…

Java JDK下载安装环境变量配置

目录 一、下载安装 1.简介 2.JDK下载JDK 官网海外历史地址&#xff1a; 3.安装 二、环境变量配置 1.新建JAVA_HOME变量 2.PATH变量 3.CLASSPATH 变量 4.测试是否安装成功 一、下载安装 1.简介 JDK 是SUN公司提供的一套Java 语言的软件开发工具包&#xff0c;简称JDK(JavaDevelo…

hvv培训的流量分析题

题目如下 1 找扫描器的特征 常见的扫描器 使用过滤语句http contains "acunetix" 2 要找到黑客的登录后台 我们可以考虑搜搜看常见的后台路径admin ip.src 192.168.94.59 && http contains "admin" 追踪下tcp流,302说明大概就是对的 3 h…

python基础实战5-python基本结构

1 if语句 if语句是用来进行判断的&#xff0c;其使用格式如下 if 要判断的条件&#xff1a; 条件成立时&#xff0c;要做的事情 案例一&#xff1a; age 30 print("------if判断开始------") if age > 18:print("我成年了") print("------if判断…

从零基础到网络安全专家:全网最全的网络安全学习路线

前言 网络安全知识体系非常广泛&#xff0c;涉及的领域也非常复杂&#xff0c;有时候即使有想法和热情&#xff0c;也不知道从何入手。 为了帮助那些想要进入网络安全行业的小伙伴们更快、更系统地学习网络安全知识&#xff0c;我制定了这份学习路线。本路线覆盖了网络安全的…

【C++】程序员必备知识:认识类与对象

【C】程序员必备知识&#xff1a;认识类与对象 ①.面向过程和面向对象②.类的引入③.类的定义Ⅰ.定义方式Ⅱ.命名规则建议&#xff1a; ④.类的访问限定符及封装Ⅰ.访问限定符Ⅱ.封装 ⑤.类的作用域⑥.类的实例化⑦.类的对象大小计算Ⅰ.如何计算&#xff1f;Ⅱ.类对象存储方式Ⅲ…

【物联网】初步认识了解MQTT

目录 一、MQTT是什么 二、MQTT的版本 两者之间的关系&#xff1a; ​编辑三、MQTT工作的基本原理 3.1、概念 MQTT客户端&#xff1a; MQTT服务端&#xff1a; MQTT主题&#xff1a; 以下面这个图为例进行解释&#xff1a; 3.2、MQTT订阅/发布主题的特点 相互可独立性…

【2023年五一数学建模竞赛C题】“双碳”目标下低碳建筑研究--完整思路和代码

1.问题背景与描述 赛题评析&#xff1a;这道题其实主要还是考察学生搜集资料的能力&#xff0c;可发挥空间大&#xff0c;适合小白快速上手 2.解题思路分析 2.1 问题一的分析 1.空调性能系数 2.热导系数 热导系数是指物质导热的能力&#xff0c;通常用单位时间内单位面积…

从STM32F407到AT32F407(一)

雅特力公司的MCU有着性能超群&#xff0c;价格优越的巨大优势&#xff0c;缺点是相关资料少一些&#xff0c;我们可以充分利用ST的现有资源来开发它。 我用雅特力的STM32F437开发板&#xff0c;使用原子 stm32f407的开发板自带程序&#xff0c;测试串口程序&#xff0c;原设定…

【网络安全】文件包含漏洞总结

目录&#xff1a; 介绍文件包含漏洞分类 LFIRFIPHP 的文件包含函数漏洞示例代码利用任意文件读取 使用 PHP 封装协议 php://filterphp://inputRFI getshellLFI文件上传 getshellLFI日志文件 getshellLFI/proc/self/environgetshellLFIphpinfo getshellLFIsession getshell绕过…