Go-知识测试-子测试

news2024/11/16 13:02:21

Go-知识测试-子测试

  • 1. 介绍
  • 2. 例子
  • 3. 子测试命名规则
  • 4. 选择性执行
  • 5. 子测试并发
  • 6. testing.T.Run
  • 7. testing.T.Parallel
  • 8. 子测试适用于单元测试
  • 9. 子测试适用于性能测试
  • 10. 总结
    • 10.1 启动子测试 Run
    • 10.2 启动并发测试 Parallel

建议先看:https://blog.csdn.net/a18792721831/article/details/140062769

Go-知识测试-工作机制

1. 介绍

子测试提供了一种在一个测试函数中执行多个测试的能力,可以自己编排执行顺序,或者做一些初始化等操作。

2. 例子

比如如下代码:

import "testing"

func SubA(t *testing.T) {
	t.Log("test A " + t.Name())
}

func SubB(t *testing.T) {
	t.Log("test B " + t.Name())
}

func SubC(t *testing.T) {
	t.Log("test C " + t.Name())
}

func TestSub(t *testing.T) {
	t.Run("name=A", SubA)
	t.Run("name=B", SubB)
	t.Run("name=C", SubC)
}

使用go test -v xx_test.go执行
在这里插入图片描述

3. 子测试命名规则

Run()方法的第一个参数作为子测试的名字,这里只是本层级的名字。
实际上子测试的内部命名规则是: <父测试名字>/<传递给Run的名字>
比如我们在B里面在调用A:
在这里插入图片描述

执行后:
在这里插入图片描述

name具有传递性

4. 选择性执行

在上面我们有 name=A,name=B,name=C 三个测试,如果只是想执行A呢
使用go test -v xx_test.go -run TestSub/name=A
在这里插入图片描述

选择性执行的字符串,是包含匹配,不是严格的正则匹配。

在这里插入图片描述

5. 子测试并发

可以看到,前面的子测试都是根据代码顺序执行,串行执行,并没有并发。
使用 t.Parallel 可以让当前测试函数允许并发。
比如如下例子不加并发的时候:

import (
	"testing"
	"time"
)

func SubA(t *testing.T) {
	t.Log("test A " + t.Name())
	time.Sleep(time.Second*3)
}

func SubB(t *testing.T) {
	t.Log("test B " + t.Name())
	time.Sleep(time.Second*2)
}

func SubC(t *testing.T) {
	time.Sleep(time.Second*1)
	t.Log("test C " + t.Name())
}

func TestSub(t *testing.T) {
	t.Run("name=A", SubA)
	t.Run("name=B", SubB)
	t.Run("name=C", SubC)
}

执行后用时超过6秒
在这里插入图片描述

允许并发:

import (
	"testing"
	"time"
)

func SubA(t *testing.T) {
	t.Parallel()
	t.Log("test A " + t.Name())
	time.Sleep(time.Second * 3)
}

func SubB(t *testing.T) {
	t.Parallel()
	t.Log("test B " + t.Name())
	time.Sleep(time.Second * 2)
}

func SubC(t *testing.T) {
	t.Parallel()
	time.Sleep(time.Second * 1)
	t.Log("test C " + t.Name())
}

func TestSub(t *testing.T) {
	t.Run("name=A", SubA)
	t.Run("name=B", SubB)
	t.Run("name=C", SubC)
}

在这里插入图片描述

A最先被调度,但是确是最后执行完毕。

需要注意的是,当开启子测试并发后,调用了子测试后,父测试的代码和子测试代码执行顺序就是随机的了。
所以如果在主测试中需要做一些初始化,然后在执行子测试,那么需要注意,有可能初始化还未完成,子测试已经开始执行了。

6. testing.T.Run

// 将运行f作为名为name的t的子测试。它在一个单独的goroutine中运行f
// 并且阻塞直到f返回或调用t。并行成为并行测试。
// 运行报告f是否成功(或者至少在调用t.Parallel之前没有失败)。
//
// Run可以从多个goroutine同时调用,但所有此类调用
// 必须在t的外部测试函数返回之前返回。
func (t *T) Run(name string, f func(t *T)) bool {
	atomic.StoreInt32(&t.hasSub, 1)
	testName, ok, _ := t.context.match.fullName(&t.common, name)
	if !ok || shouldFailFast() {
		return true
	}
	//记录此调用点的堆栈跟踪,以便如果子测试
	//在单独的堆栈中运行的函数被标记为助手,我们可以
	//继续将堆栈遍历到父测试中。
	var pc [maxStackLen]uintptr
	n := runtime.Callers(2, pc[:])
	t = &T{
		common: common{
			barrier: make(chan bool),
			signal:  make(chan bool, 1),
			name:    testName,
			parent:  &t.common,
			level:   t.level + 1,
			creator: pc[:n],
			chatty:  t.chatty,
		},
		context: t.context,
	}
	t.w = indenter{&t.common}
	if t.chatty != nil {
		t.chatty.Updatef(t.name, "=== RUN   %s\n", t.name)
	}
	//而不是在调用之前减少此测试的运行计数
	//tRunner并在之后增加它,我们依靠tRunner保持
	//计数正确。这样可以确保运行一系列顺序测试
	//而不会被抢占,即使它们的父级是并行测试。这
	//如果*parallel==1,则可以特别减少意外。
	go tRunner(t, f)
	if !<-t.signal {
		//此时,FailNow很可能是在
		//其中一个子测验的家长测验。继续中止链的上行。
		runtime.Goexit()
	}
	return !t.failed
}

在testing.Run中,会创建一个testing.T对象,然后将调用者作为parent,然后调用testing.tRunner执行。
同时会设置父测试有子测试的标志:hasSub。
一个树形结构,父测试不知道有哪些子测试,但是父测试知道需要等待子测试执行完成。

7. testing.T.Parallel

// 与此测试并行运行的并行信号(且仅与)
// 其他平行测试。当测试由于使用而多次运行时
// -test.count或-test.cpu,单个测试的多个实例从未在中运行
// 彼此平行。
func (t *T) Parallel() {
	if t.isParallel {
		panic("testing: t.Parallel called multiple times")
	}
	if t.isEnvSet {
		panic("testing: t.Parallel called after t.Setenv; cannot set environment variables in parallel tests")
	}
	t.isParallel = true
	if t.parent.barrier == nil {
		// T.Parallel has no effect when fuzzing.
		// Multiple processes may run in parallel, but only one input can run at a
		// time per process so we can attribute crashes to specific inputs.
		return
	}
	//我们不想把等待串行测试的时间包括在内
	//在测试持续时间内。记录到目前为止经过的时间,并重置
	//计时器之后。
	t.duration += time.Since(t.start)
	//添加到要由父级发布的测试列表中。
	t.parent.sub = append(t.parent.sub, t)
	t.raceErrors += race.Errors()
	if t.chatty != nil {
		//不幸的是,即使PAUSE表示命名测试是*no
		//运行时间较长*,cmd/test2json将其解释为更改活动测试
		//用于日志解析。我们可以修复cmd/test2json,但是
		//不会修复已经shell的第三方工具的现有部署
		//向外扩展到cmd/test2json的旧版本——因此仅修复cmd/test1json
		//目前还不够。
		t.chatty.Updatef(t.name, "=== PAUSE %s\n", t.name)
	}
	t.signal <- true   // Release calling test.
	<-t.parent.barrier // Wait for the parent test to complete.
	t.context.waitParallel()
	if t.chatty != nil {
		t.chatty.Updatef(t.name, "=== CONT  %s\n", t.name)
	}
	t.start = time.Now()
	t.raceErrors += -race.Errors()
}

设置当前testing.T的并发状态为true,因为Parallel在子测试中调用的,因此testing.T是子测试的T。
testing.Run是在父测试中调用的,因此testing.T是父测试。
将当前子测试加入到父测试的sub列表中,由父测试启动。

8. 子测试适用于单元测试

在testing.common中,hasSub表示是否有子测试,sub 则是子测试列表(testing.T)
在这里插入图片描述

在testing.tRunner中,有对子测试相关的支持
在这里插入图片描述

if len(t.sub) > 0 表示,如果有子测试,那么触发子测试执行,并且等待子测试执行完成。
else if t.isParallel 表示,如果是允许并发的,那么释放锁。
testing.tRunner 不管是父测试,还是子测试,都会执行。

9. 子测试适用于性能测试

在testing.B.Run中,设置父测试的hasSub标志为1。
在这里插入图片描述

并且创建一个testing.B,通过先调用testing.B.run1在调用testing.B.run执行。
并且子测试的数据会附加到父测试的报告中。

10. 总结

10.1 启动子测试 Run

Run 函数启动一个单独的协程来运行名字为name的子测试f,并且会阻塞等待其执行结束,除非子测试f显式调用Parallel将自己编程一个可并行的测试,最后返回bool类型的测试结果。
所有的测试,都是由TestMain使用Run方法直接或者间接启动。
每启动一个子测试,都会创建一个testing.T或者testing.B变量,该变量集成当前测试的部分属性,然后以新的
协程执行,当前测试会在子测试结束后返回子测试的结果。
子测试退出条件要么是子测试执行结束,要么是子测试设置了Parallel,否则是异常退出。

10.2 启动并发测试 Parallel

Parallel方法将当前测试加入并发队列。
启动并发测试,在排队等待过程中,消耗的时间不能统计到测试的耗时内,所以在测试真正被并发调度后,清空等待时间。

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

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

相关文章

LinK3D: Linear Keypoints Representation for 3D LiDAR Point Cloud【翻译与解读】

LinK3D: Linear Keypoints Representation for 3D LiDAR Point Cloud 摘要 特征提取和匹配是许多机器人视觉任务的基本组成部分&#xff0c;如 2D 或 3D 目标检测、识别和配准。2D 特征提取和匹配已取得巨大成功。然而&#xff0c;在 3D 领域&#xff0c;当前方法由于描述性差…

手机大模型能否撑起“全村的希望”?

2023年&#xff0c;ChatGPT、SD的火爆带火了AI赛道。但现有的AI痛点则是&#xff1a;操作复杂&#xff0c;需要网络&#xff0c;大家对本地AI的呼声越来越高。也因此产生了AI PC和手机上装上大模型。手机上装大模型&#xff0c;确实会对现在低迷的手机市场带来一些影响&#xf…

链路追踪系列-02.演示zipkin

当本机启动docker es zipkinServer之后&#xff1a; 启动3个项目&#xff1a;先eureka-server&#xff0c;再 PaymentMain8001,… 浏览器打开&#xff1a;http://localhost:9001/consumer/payment/zipkin consumer代码 &#xff1a; provider: 此时查询es:

安全防御----防火墙综合实验2

安全防御----防火墙综合实验2 一、题目 二、实验要求&#xff1a; 1&#xff0c;DMZ区内的服务器&#xff0c;办公区仅能在办公时间内&#xff08;9&#xff1a;00 - 18&#xff1a;00&#xff09;可以访问&#xff0c;生产区的设备全天可以访问. 2&#xff0c;生产区不允许访…

微积分-导数7(关联变化率)

例一 空气被充入一个球形气球中&#xff0c;使其体积以每秒100立方厘米的速度增加。当气球的直径为50厘米时&#xff0c;气球半径的增加速度是多少&#xff1f; 解答&#xff1a;球体的体积公式为 V 4 3 π r 3 V \frac{4}{3}\pi r^3 V34​πr3 为了使用给定的信息&#x…

Java中标识符和关键字

1.标识符 public class HelloWorld{public static void main(String[] args){System.out.println("Hello,world");} }上述代码中在public class 后面的HelloWorld称为类名&#xff0c;main称为方法名&#xff0c;也可以将其称为标识符&#xff0c;即&#xff1a;在程…

数组和对象的解构

1.解构的理解 解构是ES6提供的一种新提取数据的模式&#xff0c;它允许我们从数组或对象中有针对性拿到想要的数据。这种方式让数据访问和赋值变得更加简洁和直观。 2.数组的解构 数组解构允许直接从数组中提取值&#xff0c;并将这些值赋给声明的变量。这避免了使用索引来访…

802.11be MRU - 多资源单元

Wi-Fi 6中引入了OFDMA技术&#xff0c;频率资源以RU(Resource Unit)为粒度进行分配&#xff0c;Wi-Fi 6中支持26/52/106/242/484/996/2x996 Tone共计7种RU。Wi-Fi 7由于引入了320MHz 信道&#xff0c;则会多一种RU类型。不同信道带宽下&#xff0c;不同类型RU的数量如下图所示。…

通用型I2C接口的应用之综合应用(N32G45XVL-STB)

通用型I2C接口的应用之综合应用&#xff08;N32G45XVL-STB&#xff09; 目录 概述 1 软硬件接口 1.1 硬件接口 1.2 开发软硬件信息 1.3 SHT-20模块电路 1.4 0.9寸OLED模块介绍 2 驱动接口实现 2.1 SHT20驱动接口 2.2 OLED驱动接口 3 应用接口实现 3.1 软件框架 3.…

捷配笔记-PCB阻焊颜色对产品有什么影响?

阻焊层也称为阻焊层或阻焊剂。它是一种薄的聚合物层&#xff0c;应用于&#xff08;PCB&#xff09;。阻焊层的目的是保护PCB表面&#xff0c;并有助于防止焊桥。焊桥是两个导体之间的无意连接&#xff0c;通常是由于存在一小块焊料。需要注意的是&#xff0c;阻焊层被视为其单…

SSM整合及使用

SSM整合 介绍 SSM&#xff08;SpringSpringMVCMyBatis&#xff09;框架集由Spring、MyBatis两个开源框架整合而成&#xff08;SpringMVC是Spring中的部分内容&#xff09;&#xff0c;常作为数据源较简单的web项目的框架。 步骤 SSM整合主要是将各个框架的核心组件都交给sprin…

【机器学习】和【人工智能】在航空航天中的应用

作者主页: 知孤云出岫 目录 引言机器学习和人工智能在航空航天中的应用1. 预测性维护2. 飞行路径优化3. 自动驾驶飞行器 未来展望1. 增强人机协作2. 更智能的空中交通管理3. 高效的航空制造 结论参考文献 引言 随着科技的迅猛发展&#xff0c;机器学习和人工智能&#xff08;…

Goland 通道

channel通道 目录 channel通道 channel介绍 channel基本使用 有缓存通道和无缓存通道的区别 通道的初始化&#xff0c;写入数据到通道&#xff0c;从通道读取数据及基本的注意事项 channel的关闭和遍历 channel的关闭 为什么关闭 如何优雅地关闭通道 channel的遍历 chan…

亚马逊插件安装教程,新手必学的两个选品步骤

亚马逊插件安装教程&#xff0c;跟卖新手必学&#xff0c;选品两个步骤。 大家好&#xff0c;今天讲下erp的插件下载和跟卖采集。erp更新到13.8版本了。 点击右上角的插件下载&#xff0c;已经下载到桌面了&#xff0c;已被压缩。 点击设置&#xff0c;选择扩展&#xff0c;…

python-亲和数(赛氪OJ)

[题目描述] 古希腊数学家毕达哥拉斯在自然数研究中发现&#xff0c;220 的所有真约数(即不是自身的约数)之和为&#xff1a; 1245101120224455110&#xff1d;284 。 而 284 的所有真约为 1 、 2 、 4 、 71 、 142 &#xff0c;加起来恰好为 220 。人们对这样的数感到很惊奇&a…

【研路导航】重庆大学计算机保研面试真题分享交流

写在前面 在保研的道路上&#xff0c;面试是非常重要的一环。这里是成功保研到重庆大学的学长的计算机保研面试的部分真题及详细解答 ! Q 快速排序和合并排序&#xff1a; 快速排序(quicksort) 和合并排序(merge sort) 两种方法都将输入的待排序序列划分为2个子序列&#xf…

centos单机配置多个内网IP地址

centos单机配置多个内网IP地址 引配置1. 查看当前网络IP配置2. 打开网络配置目录3. 设置静态IP4. 编辑ifcfg-eno1:15. 重启网络配置 引 同一个局域网&#xff0c;但是对接的多个子系统使用了不同的网段&#xff0c;如一个系统主机IP地址是192.168.10.1&#xff0c;另一个系统主…

2024 辽宁省大学数学建模竞赛A题 风切变影响及处置 完整思路 代码结果分享(仅供学习)

风切变对航空安全会构成危害。航空人员需了解相关知识&#xff0c;掌握相应技术&#xff0c;从而在遭遇上述天气时最大程度的规避风险&#xff0c;保证飞行安全。 风切变是指在大气中相对比较短的距离内或时间段内产生的风速大小、方向大幅度变化的现象。通常将发生在距离地面…

Rust Hello

首先还是安装&#xff1a; 一定要换源&#xff0c;否则真的太慢了。 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh 就是~/.cargo/config [source.crates-io] # 替换成你偏好的镜像源 replace-with tuna# 清华大学 5mb [source.tuna] registry "htt…

课程的概述

课程概述 课程类型 课程理论流派 制约课程开发的因素 课程设计的概念及两种模式 课程内容 课程评价 新课程改革理念