golang单元测试性能测试常见用法

news2024/9/22 0:53:40

9c25ec5ae6cbdb2bb889ff4d4ef4ceda.jpeg

关于go test的一些说明

  • golang安装后可以使用go test工具进行单元测试 代码片段对比的性能测试,使用起来还是比较方便,下面是一些应用场景
    • 平时自己想做一些简单函数的单元测试,不用每次都新建一个main.go 然后go run main.go
    • 相对某个功能做下性能测试 看下cpu/内存消耗情况
  • 可以针对性的建立一些目录 存放自己的一些测试代码
  • 一些使用规则
    • 创建代码保存目录 这里以mytest目录为例
    • 目录下的文件名都要以_test.go结尾 比如common_test.go
    • package mytest 不要为main
    • import testing包
    • 普通单元测试 函数名以Test开头
    • 性能测试 函数名称以Benchmark开头
    • 目录下面函数名不要重名

普通单元测试常见用法

样例代码

  • common_test.go文件内容如下 一个加法函数一个乘法函数
  • package mytest
  • import "testing"

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

    // Mul 乘法
    func Mul(a int, b int) int {
    return a * b
    }

    // 测试加法函数功能是否正常 正数
    func TestAddPositive(t *testing.T) {
    if ans := Add(1, 2); ans != 3 {
    t.Fatalf("1 + 2 expected be 3, but %d got", ans)
    }
    t.Log("TestAddPositive run Success")
    }

    // 测试加法函数功能是否正常 负数
    func TestAddNegative(t *testing.T) {
    if ans := Add(-10, -20); ans != -30 {
    t.Fatalf("-10 + -20 expected be -30, but %d got", ans)
    }
    t.Log("TestAddNegative run Success")
    }

    // 测试乘法函数功能是否正常
    func TestMul(t *testing.T) {
    if ans := Mul(3, 4); ans != 12 {
    t.Fatalf("3*4 expected be 12, but %d got", ans)
    }
    t.Log("TestMul run Success")
    }


指定文件测试

  • 命令 顺序测试文件中的所有函数
  • go test -v common_test.go
    • 假设mytest目录下有多个xx_test.go文件 想指定common_test.go文件中的所有函数
  • 输出
  • === RUN TestAddPositive
    common_test.go:20: TestAddPositive run Success
    --- PASS: TestAddPositive (0.00s)
    === RUN TestAddNegative
    common_test.go:28: TestAddNegative run Success
    --- PASS: TestAddNegative (0.00s)
    === RUN TestMul
    common_test.go:36: TestMul run Success
    --- PASS: TestMul (0.00s)
    PASS
    ok command-line-arguments 0.309s


指定测试某一个函数

  • 命令
  • go test -v -run TestAddPositive
    go test -run=TestAddPositive -v
    • 指定只测试目录下的TestAddPositive函数
  • 输出
  • === RUN TestAddPositive
    common_test.go:20: TestAddPositive run Success
    --- PASS: TestAddPositive (0.00s)
    PASS
    ok mytest 0.307s


指定测试某一类函数

  • 命令
  • go test -run=^TestAdd -v
    • 可以使用正则表达式 指定一类函数,比如想测试所有TestAdd开头的函数
  • 输出 会按照顺序测试目录下所有TestAdd打头的函数
  • === RUN TestAddPositive
    common_test.go:20: TestAddPositive run Success
    --- PASS: TestAddPositive (0.00s)
    === RUN TestAddNegative
    common_test.go:28: TestAddNegative run Success
    --- PASS: TestAddNegative (0.00s)
    PASS
    ok mytest 0.359s


测试目录下所有文件中的全部函数

  • 命令 会按照顺序测试目录下所有_test.go结尾的所有函数
  • go test -v .

性能测试的常见用法

样例代码

  • forRangeBenchMark_test.go样例代码如下
  • package mytest

    import "testing"

    // ************ benchmark range loop ************
    type Person struct {
    name [4096]byte
    age int
    }

    var (
    AllPerson [1024]Person
    )

    // BenchmarkForIndexVisit AllPerson[i].xxx 使用下标方式访问
    func BenchmarkForIndexVisit(b *testing.B) {
    for i := 0; i < b.N; i++ {
    var age int
    for i := 0; i < len(AllPerson); i++ {
    age = AllPerson[i].age
    }
    _ = age
    }
    }

    // BenchmarkRangeLoopVisit range循环的方式访问
    func BenchmarkRangeLoopVisit(b *testing.B) {
    for i := 0; i < b.N; i++ {
    var age int
    for _, person := range AllPerson {
    age = person.age
    }
    _ = age
    }
    }


-benchmem会打印内存申请信息,建议都打开这个选项

指定某一个文件测试

  • 命令
  • go test -bench=. -benchmem forRangeBenchMark_test.go
  • 输出
  • goos: darwin
    goarch: amd64
    cpu: Intel(R) Core(TM) i5-9600K CPU @ 3.70GHz
    BenchmarkForIndexVisit-6 4570186 246.8 ns/op 0 B/op 0 allocs/op
    BenchmarkRangeLoopVisit-6 4777 228750 ns/op 0 B/op 0 allocs/op
    PASS
    ok command-line-arguments 2.858s
  • 这里可以看出直接for range的方式遍历性能很差 因为for range会有一个临时变量复制的过程,这个过程比较消耗时间


指定某一个函数测试

  • 命令
  • go test -bench=BenchmarkRangeLoopVisit -benchmem
  • 输出
  • goos: darwin
    goarch: amd64
    pkg: mytest
    cpu: Intel(R) Core(TM) i5-9600K CPU @ 3.70GHz
    BenchmarkRangeLoopVisit-6 4657 345054 ns/op 0 B/op 0 allocs/op
    PASS
    ok mytest 1.950s


指定某一类函数

  • 命令
  • go test -bench=^BenchmarkRange -benchmem
    • 所有以BenchmarkRange打头的都会测试


指定测试时间

  • 命令
  • go test -bench=. -benchmem forRangeBenchMark_test.go -benchtime=5s
    • 默认1s 下面指定运行时间为5s
  • 输出
  • goos: darwin
    goarch: amd64
    cpu: Intel(R) Core(TM) i5-9600K CPU @ 3.70GHz
    BenchmarkForIndexVisit-6 24010926 248.3 ns/op 0 B/op 0 allocs/op
    BenchmarkRangeLoopVisit-6 24183 242653 ns/op 0 B/op 0 allocs/op
    PASS
    ok command-line-arguments 14.918s
    • BenchmarkForIndexVisit函数在5s内运行了24010926次 每次大概耗时 248.3 ns
    • BenchmarkRangeLoopVisit函数在5s内运行了24183次 每次大概耗时 242653 ns 性能相当差


指定测试次数

  • 命令
  • go test -bench=. -benchmem forRangeBenchMark_test.go -benchtime=10000x
  • 输出
  • goos: darwin
    goarch: amd64
    cpu: Intel(R) Core(TM) i5-9600K CPU @ 3.70GHz
    BenchmarkForIndexVisit-6 10000 246.6 ns/op 0 B/op 0 allocs/op
    BenchmarkRangeLoopVisit-6 10000 300624 ns/op 0 B/op 0 allocs/op
    PASS
    ok command-line-arguments 3.347s
    • 测试过程也可以看到BenchmarkRangeLoopVisit运行耗时很长,而BenchmarkForIndexVisit很快就结束了


性能测试-timer相关api

ResetTimer

  • 如果在 benchmark 开始前,需要一些准备工作,如果准备工作比较耗时,则需要将这部分代码的耗时忽略掉

StopTimer & StartTimer

  • 每次函数调用前后需要一些准备工作和清理工作,我们可以使用 StopTimer 暂停计时以及使用 StartTimer 开始计时
  • func Benchmarkxxx(b *testing.B) {
    for n := 0; n < b.N; n++ {
    b.StopTimer()
    // 准备数据
    b.StartTimer()
    Sort(nums)
    }
    }
    func Benchmarkxxx(b *testing.B) {
    //准备工作部分代码
    b.ResetTimer() // 重置定时器
    for n := 0; n < b.N; n++ {
    fib(30) // run fib(30) b.N times
    }
    }

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

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

相关文章

Anthropic推出1亿美元AI基金,加剧与OpenAI的竞争|TodayAI

人工智能初创公司Anthropic和风险投资公司Menlo Ventures宣布&#xff0c;他们将共同推出一支价值1亿美元的基金&#xff0c;以支持早期初创公司并推动它们使用Anthropic的技术。这个名为Anthology Fund的新基金&#xff0c;将为初创公司提供资金和技术支持&#xff0c;旨在模仿…

三、GPIO口

我们在刚接触C语言时&#xff0c;写的第一个程序必定是hello world&#xff0c;其他的编程语言也是这样类似的代码是告诉我们进入了编程的世界&#xff0c;在单片机中也不例外&#xff0c;不过我们的传统就是点亮第一个LED灯&#xff0c;点亮电阻&#xff0c;电容的兄弟&#x…

锁策略和CAS指令

锁策略 一、锁策略的引入二、锁策略的分类&#xff08;1&#xff09;乐观锁和悲观锁&#xff08;2&#xff09;重量级锁和轻量级锁&#xff08;3&#xff09; 自旋锁和挂起等待锁&#xff08;4&#xff09;可重入锁和不可重入锁&#xff08;5&#xff09;公平锁和非公平锁&…

SQL面试题练习 —— 统计最大连续登录天数区间

目录 1 题目2 建表语句3 题解 1 题目 2 建表语句 CREATE TABLE IF NOT EXISTS user_login_tb (uid INT,login_date DATE ); insert into user_login_tb(uid, login_date) values( 1, 2022-08-02),(1, 2022-08-03),(2, 2022-08-03),(2, 2022-08-04),(2, 2022-08-05),(2, 2022-08…

使用Python的Turtle模块绘制小黄人

引言 在Python编程的世界里&#xff0c;turtle 模块是一个非常有趣且实用的工具&#xff0c;它允许程序员通过简单的指令控制一个虚拟的画笔&#xff08;称为“海龟”&#xff09;在屏幕上移动和绘制图形。本篇博客将详细介绍如何使用turtle模块来绘制一个卡通人物&#xff0c…

Redis-布隆过滤器(Bloom Filter)详解

文章目录 什么是布隆过滤器 布隆过滤器的优点&#xff1a;布隆过滤器的缺点&#xff1a;其他问题 布隆过滤器适合的场景布隆过滤器原理 数据结构增加元素查询元素删除元素 如何使用布隆过滤器 Google开源的Guava自带布隆过滤器Redis实现布隆过滤器 Redis中配置布隆过滤器Redis…

给Wordpress添加评分功能到评论表单

今天要 给你的 Wordpress 添加评分功能到评论表单 吗&#xff1f; 评分功能效果图 什么类型的网站需要评分&#xff1f; 资源站教程站其他&#xff0c;我也没想到。。。 但我这个网站&#xff0c;因为是电影类的网站&#xff0c;好像还是有点需要的&#xff0c;所以&#xf…

完美的用户体验:如何设计一个直观和有效的网站导航?

APP的顶部导航栏对我们来说很熟悉。导航栏是UI设计中不可或缺的一部分&#xff0c;几乎每个页面都使用导航栏。虽然导航栏看起来很简单&#xff0c;不需要太多精力&#xff0c;但是设计一个与产品需求和客户目标高度匹配的导航栏并不是那么容易的。导航栏的设计标准有很多细节需…

SpringBoot集成MQTT实现交互服务通信

引言 本文是springboot集成mqtt的一个实战案例。 gitee代码库地址&#xff1a;源码地址 一、什么是MQTT MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;&#xff0c;是一种基于发布/订阅&#xff08;publish/subscribe&…

C++ : 移除链表元素/合并两个有序链表题解

目录 1.移除链表元素 分析 代码 2.合并两个有序链表 分析 代码 1.移除链表元素 分析 像这种移除元素的&#xff0c;加个哨兵位头节点会比较方便&#xff0c;因为旧的头会有被移除的情况&#xff0c;不好控制。这里只需要用cur指向待遍历的节点&#xff0c;prev指向cur的…

AI大牛Karpathy创办Eureka Labs专注AI+教育

&#x1f989; AI新闻 &#x1f680; AI大牛Karpathy创办Eureka Labs专注AI教育 摘要&#xff1a;前OpenAI大牛Karpathy离职半年后宣布创办专注AI与教育的公司Eureka Labs&#xff0c;旨在通过生成式AI优化教育体验。公司首个项目LLM101n课程已在GitHub获得高赞&#xff0c;目…

C++ 继承详解:从基础到深入

继承是面向对象编程中最强大的功能之一&#xff0c;它不仅促进了代码的重用&#xff0c;还帮助我们构建复杂的系统。在C中&#xff0c;通过继承&#xff0c;我们可以创建一个新的类&#xff08;称为派生类&#xff09;来扩展现有类&#xff08;基类&#xff09;的功能。本文将全…

基于python的百度资讯爬虫的设计与实现

研究背景 随着互联网和信息技术的飞速发展&#xff0c;网络已经成为人们获取信息的主要来源之一。特别是搜索引擎&#xff0c;作为信息检索的核心工具&#xff0c;极大地改变了人们获取信息的方式。其中&#xff0c;百度作为中国最受欢迎的搜索引擎之一&#xff0c;其新闻搜索…

[GXYCTF2019]Ping Ping Ping1

打开靶机 结合题目名称&#xff0c;考虑是命令注入&#xff0c;试试ls 结果应该就在flag.php。尝试构造命令注入载荷。 cat flag.php 可以看到过滤了空格,用 $IFS$1替换空格 还过滤了flag&#xff0c;我们用字符拼接的方式看能否绕过,ag;cat$IFS$1fla$a.php。注意这里用分号间隔…

【总结】逻辑运算在Z3中运用+CTF习题

国际赛IrisCTF在前几天举办&#xff0c;遇到了一道有意思的题目&#xff0c;特来总结。 题目 附件如下&#xff1a;&#x1f4ce;babyrevjohnson.tar 解题过程 关键main函数分析如下&#xff1a; int __fastcall main(int argc, const char **argv, const char**envp){int v4…

Golang | Leetcode Golang题解之第236题二叉树的最近公共祖先

题目&#xff1a; 题解&#xff1a; func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {parent : map[int]*TreeNode{}visited : map[int]bool{}var dfs func(*TreeNode)dfs func(r *TreeNode) {if r nil {return}if r.Left ! nil {parent[r.Left.Val] rdfs(r.L…

用 WireShark 抓住 TCP

Wireshark 是帮助我们分析网络请求的利器&#xff0c;建议每个同学都装一个。我们先用 Wireshark 抓取一个完整的连接建立、发送数据、断开连接的过程。 简单的介绍一下操作流程。 1、首先打开 Wireshark&#xff0c;在欢迎界面会列出当前机器上的所有网口、虚机网口等可以抓取…

气膜体育馆进校园:政策支持与市场前景—轻空间

过去20多年&#xff0c;气膜建筑、场馆相关项目在国内落地众多&#xff0c;展现出强大的市场潜力。2022年8月&#xff0c;《北京晚报》粗略统计&#xff0c;北京全市已建有气膜馆百余座&#xff0c;且数量还在不断增加。这一发展趋势不仅仅体现在北京&#xff0c;全国范围内也都…

微软GraphRAG +本地模型+Gradio 简单测试笔记

安装 pip install graphragmkdir -p ./ragtest/input#将文档拷贝至 ./ragtest/input/ 下python -m graphrag.index --init --root ./ragtest修改settings.yaml encoding_model: cl100k_base skip_workflows: [] llm:api_key: ${GRAPHRAG_API_KEY}type: openai_chat # or azu…

如何通过企业微信会话存档保护企业利益?

赵总: 张经理&#xff0c;最近行业内频发数据泄露事件&#xff0c;我们的客户资料和内部沟通记录安全吗&#xff1f; 张经理: 赵总&#xff0c;我们已经采取了一系列措施来加强数据安全。特别是针对企业微信的沟通记录&#xff0c;我们最近引入了安企神软件&#xff0c;它能很…