当前位置: 首页 > news >正文

Go test 命令工作原理

为什么80%的码农都做不了架构师?>>>   hot3.png

前言

前面的章节我们分析了每种测试的数据结构及其实现原理,本节我们看一下go test的执行机制。

Go 有多个命令行工具,go test只是其中一个。go test命令的函数入口在src\cmd\go\internal\test\test.go:runTest(),这个函数就是go test的大脑。

runTest()

runTest()函数场景如下:

func runTest(cmd *base.Command, args []string)

GO 命令行工具的实现中,都遵循这种函数声明,其中args即命令行输入的全部参数。

runTest首先会分析所有需要测试的包,为每个待测包生成一个二进制文件,然后执行。

两种运行模式

go test运行时,跟据是否指定package分为两种模式,即本地目录模式和包列表模式。

本地目录模式

当执行测试并没有指定package时,即以本地目录模式运行,例如使用"go test"或者"go test -v"来启动测试。

本地目录模式下,go test编译当前目录的源码文件和测试文件,并生成一个二进制文件,最后执行并打印结果。

包列表模式

当执行测试并显式指定package时,即以包列表模式运行,例如使用"go test math"来启动测试。

包列表模式下,go test为每个包生成一个测试二进制文件,并分别执行它。 包列表模式是在Go 1.10版本才引入的,它会把每个包的测试结果写入到本地临时文件中做为缓存,下次执行时会直接从缓存中读取测试结果,以便节省测试时间。

缓存机制

当满足一定的条件,测试的缓存是自动启用的,也可以显式的关闭缓存。

测试结果缓存

如果一次测试中,其参数全部来自"可缓存参数"集合,那么本次测试结果将被缓存。

可缓存参数集合如下:

  • -cpu
  • -list
  • -parallel
  • -run
  • -short
  • -v

需要注意的是,测试参数必须全部来自这个集合,其结果才会被缓存,没有参数或包含任一此集合之外的参数,结果都不会缓存。

使用缓存结果

如果满足条件,测试不会真正执行,而是从缓存中取出结果并呈现,结果中会有"cached"字样,表示来自缓存。

使用缓存结果也需要满足一定的条件:

  • 本次测试的二进制及测试参数与之前的一次完全一致;
  • 本次测试的源文件及环境变量与之前的一次完全一致;
  • 之前的一次测试结果是成功的;
  • 本次测试运行模式是列表模式

下面演示一个使用缓存的例子:

E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src>go test gotest
ok      gotest  3.434s

E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src>go test gotest
ok      gotest  (cached)

前后两次执行测试,参数没变,源文件也没变化,第二次执行时会自动从缓存中获取结果,结果中“cached”即表示结果从缓存中获取。

禁用缓存

测试时使用一个不在“可缓存参数”集合中的参数,就不会使用缓存,比较常用的方法是指定一个参数“-count=1”。

下面演示一个禁用缓存的例子:

E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src>go test gotest
ok      gotest  3.434s

E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src>go test gotest
ok      gotest  (cached)

E:\OpenSource\GitHub\RainbowMango\GoExpertProgrammingSourceCode\GoExpert\src>go test gotest -count=1
ok      gotest  3.354s

第三次执行使用了参数"-count=1",所以执行时不会从缓存中获取结果。

赠人玫瑰手留余香,如果觉得不错请给个赞~

本篇文章已归档到GitHub项目,求星~ 点我即达

转载于:https://my.oschina.net/renhc/blog/3015711

相关文章:

  • 监控Linux系统状态、手动增加swap空间
  • React16时代,该用什么姿势写 React ?
  • 今年的LC3大会没了?
  • 戴姆勒与宝马抱团开发自动驾驶 新旧车企大战在即
  • TableStore多元索路由探微
  • JPress v2.0-rc.4 发布,修复插件安装卸载的若干问题
  • 002_python基础语录
  • redis事务和脚本
  • Spring源码分析(六)SpringAOP实例及标签的解析
  • Nodejs教程11:assert(断言)
  • use Google search engine
  • 【zookeeper源码】启动流程详解
  • Linux 搭建 Jenkins
  • 新技术到底靠不靠谱?在中国用一下就知道了
  • 设计模式 —— 建造者模式
  • JS 中的深拷贝与浅拷贝
  • [笔记] php常见简单功能及函数
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • Java Agent 学习笔记
  • js
  • MYSQL 的 IF 函数
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • vagrant 添加本地 box 安装 laravel homestead
  • 产品三维模型在线预览
  • 如何设计一个比特币钱包服务
  • 字符串匹配基础上
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (14)Hive调优——合并小文件
  • (145)光线追踪距离场柔和阴影
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (层次遍历)104. 二叉树的最大深度
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (数据结构)顺序表的定义
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • *上位机的定义
  • .htaccess配置常用技巧
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .NET 中让 Task 支持带超时的异步等待
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .NET/C# 使用反射注册事件
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .NET企业级应用架构设计系列之应用服务器
  • [2016.7.Test1] T1 三进制异或
  • [cb]UIGrid+UIStretch的自适应
  • [Django开源学习 1]django-vue-admin
  • [Docker]六.Docker自动部署nodejs以及golang项目
  • [HTML]Web前端开发技术18(HTML5、CSS3、JavaScript )HTML5 基础与CSS3 应用——喵喵画网页
  • [JavaEE系列] wait(等待) 和 notify(唤醒)
  • [LeetCode] Copy List with Random Pointer 拷贝带有随机指针的链表
  • [Lucas定理]【学习笔记】
  • [MySQL]基础的增删改查
  • [NOIP2014] 提高组 洛谷P1941 飞扬的小鸟