一键生成!如何为整个go项目自动添加单测

news2024/10/5 13:48:23

效果

为go项目中每个go文件生成对应的test文件,为每个接口生成对应的单测接口。

类似于这样,为go项目中每个包都生成一个test文件,单测模板如下:

比如函数接口为func releaseEndpoint(instanceID string, endpointID string) error

生成的单测为:

准备工具

GitHub - cweill/gotests: Automatically generate Go test boilerplate from your source code.

下载命令:

$ go get -u github.com/cweill/gotests/...

使用方式(可以按照自己的想法设置):

Usage of gotests:
  -all
        generate tests for all functions and methods
  -excl string
        regexp. generate tests for functions and methods that don't match. Takes precedence over -only, -exported, and -all
  -exported
        generate tests for exported functions and methods. Takes precedence over -only and -all
  -i    print test inputs in error messages
  -nosubtests
        disable generating tests using the Go 1.7 subtests feature
  -only string
        regexp. generate tests for functions and methods that match only. Takes precedence over -all
  -parallel
        enable generating parallel subtests
  -template string
        optional. Specify custom test code templates, e.g. testify. This can also be set via environment variable GOTESTS_TEMPLATE
  -template_dir string
        optional. Path to a directory containing custom test code templates. Takes precedence over -template. This can also be set via environment variable GOTESTS_TEMPLATE_DIR
  -template_params string
        read external parameters to template by json with stdin
  -template_params_file string
        read external parameters to template by json with file
  -w    write output to (test) files instead of stdout

准备模板

gotests工具是会准备一套自用的模板的,位置在:gotests/internal/render/templates at develop · cweill/gotests · GitHub

比较重要的是function.tmpl,我们可以自定义,下面是我自用的,仅供参考

{{define "function"}}
{{- $f := .}}

func {{.TestName}}(t *testing.T) {
	{{- with .Receiver}}
		{{- if .IsStruct}}
			{{- if .Fields}}
				type fields struct {
				{{- range .Fields}}
					{{Field .}} {{.Type}}
				{{- end}}
				}
			{{- end}}
		{{- end}}
	{{- end}}
	{{- if .TestParameters}}
	type args struct {
		{{- range .TestParameters}}
				{{Param .}} {{.Type}}
		{{- end}}
	}
	{{- end}}
	tests := []struct {
		name string
		{{- with .Receiver}}
			{{- if and .IsStruct .Fields}}
				fields fields
			{{- else}}
				{{Receiver .}} {{.Type}}
			{{- end}}
		{{- end}}
		{{- if .TestParameters}}
			args args
		{{- end}}
		{{- range .TestResults}}
			{{Want .}} {{.Type}}
		{{- end}}
		{{- if .ReturnsError}}
			wantErr bool
		{{- end}}
	}{
		// TODO: Add test cases.
	}
	for {{if (or .Subtests (not .IsNaked))}} _, tt := {{end}} range tests {
		{{- if .Parallel}}tt := tt{{end}}
		mockey.PatchConvey(fmt.Sprintf("{{.TestName}}:%s", tt.name), t, func() {
			{{- if .Parallel}}t.Parallel(){{end}}
			
			// mock func here
			// mockey.Mock(...).Return...).Build()

			{{- with .Receiver}}
				{{- if .IsStruct}}
					{{Receiver .}} := {{if .Type.IsStar}}&{{end}}{{.Type.Value}}{
					{{- range .Fields}}
						{{.Name}}: tt.fields.{{Field .}},
					{{- end}}
					}
				{{- end}}
			{{- end}}
			{{- range .Parameters}}
				{{- if .IsWriter}}
					{{Param .}} := &bytes.Buffer{}
				{{- end}}
			{{- end}}
			{{- if and (not .OnlyReturnsError) (not .OnlyReturnsOneValue) }}
				{{template "results" $f}} {{template "call" $f}}
			{{- end}}
			{{- if .ReturnsError}}
				if {{if .OnlyReturnsError}} err := {{template "call" $f}}; {{end}} (err != nil) != tt.wantErr {
					t.Errorf("{{template "message" $f}} error = %v, wantErr %v", {{template "inputs" $f}} err, tt.wantErr)
					{{- if .TestResults}}
						{{if .Subtests }}return{{else}}continue{{end}}
					{{- end}}
				}
			{{- end}}
			{{- range .TestResults}}
				{{- if .IsWriter}}
					if {{Got .}} := {{Param .}}.String(); {{Got .}} != tt.{{Want .}} {
				{{- else if .IsBasicType}}
					if {{if $f.OnlyReturnsOneValue}}{{Got .}} := {{template "inline" $f}}; {{end}} {{Got .}} != tt.{{Want .}} {
				{{- else}}
					if {{if $f.OnlyReturnsOneValue}}{{Got .}} := {{template "inline" $f}}; {{end}} !reflect.DeepEqual({{Got .}}, tt.{{Want .}}) {
				{{- end}}
				t.Errorf("{{template "message" $f}} {{if $f.ReturnsMultiple}}{{Got .}} {{end}}= %v, want %v", {{template "inputs" $f}} {{Got .}}, tt.{{Want .}})
				}
			{{- end}}
		{{- if .Subtests }} }) {{- end -}}
	}
}

{{end}}

go项目ut生成方式

$gotests -i -template_dir $templ_dir -all -w $file > /dev/null

其中templ_dir指的是模板绝对路径,file指的是想要生成ut的go文件。

针对整个项目

写一个sh脚本来进行遍历,筛选go文件并生成:

#!/usr/bin/env bash

# ===================================================================
# build ut test
# ===================================================================

pwd_dir=`pwd`
gotests=$pwd_dir/ut/gotests
templ_dir=$pwd_dir/ut/templates

# 跳过的文件
ignore_dir=(\
    "$pwd_dir/ut" \
    "$pwd_dir/output" \
    "$pwd_dir/model" \
)

function is_ignore_dir(){
    for i in ${ignore_dir[@]}
    do
        if [ $1 == $i ]
        then
            return 1
        fi
    done
    return 0
}

function build_ut(){
    if [ -d $1 ]
    then
        is_ignore_dir $1
        if [ $? == 1 ]
        then
            return
        fi
    else
        return
    fi

    # 生成ut test文件
    go_file_list=(`ls $1|grep '.go' |grep -v '_test.go'`)
    for file in ${go_file_list[@]}
    do
        $gotests -i -template_dir $templ_dir -all -w $1"/"$file > /dev/null
    done

    for file in `ls $1`
    do
        build_ut $1"/"$file
    done
}

build_ut $pwd_dir

这里我还添加了需要忽视的文件夹的选项,可以自行添加,添加后会跳过,不再生成ut。

准备好脚本后,在自己的go项目中调用即可!!

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

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

相关文章

微信小程序中使用 wx.getLocation获取当前详细位置并计算距离

文章目录 前言1,wx.getLocation()2,获取详细地址3,计算距离4,报错信息: getLocation:fail 频繁调用会增加电量损耗5,报错信息: 请求源未被授权 前言 wx.getLocation只能够获取经纬度&#xff0c…

java Maven 的理解

一、maven项目产生的原因 当开发两个Java项目,姑且把它们称为A、B,其中A项目中的一些功能依赖于B项目中的某些类,那么如何维系这种依赖关系的呢? 答:可以将B项目打成jar包,然后在A项目的Library下导入B的ja…

保姆级教程|昨晚撸了一个ChatGPT群聊机器人

前言 近期ChatGPT可以说是太火了,问答、写论文、写诗、写代码,只要输入精确的prompt,他的表现总是让人惊喜。本着打不过就加入的原则。要是把ChatGPT拉入群聊中,会是怎样一番场景?说做就做,花了1个晚上捣鼓…

ChatGPT与文心一言对比思考

ChatGPT与文心一言对比思考 1. 目前在国内比较广泛被认知的ai模型有什么 我目前通过各种渠道注册到的账号有3个,按照了解到然后注册的顺序分别是 ChatGPTnewbing文心一言 3种ai的注册渠道 ChatGPT注册: 科学上网注册寻找外网手机号发送短信 newbing注册: 科学上网注册微软账…

政企数智办公巡展回顾 | 通信赋能传统行业数智化转型的应用实践

在宏观政策引导、技术革新与企业内部数字化改革需求的共同驱使下,数智办公已经成为各行各业转型升级的必由之路。关注【融云 RongCloud】,了解协同办公平台更多干货。 近期,“连接无界 智赋未来” 融云 2023 政企数智办公巡展在北京、杭州相…

【Java】EnumSet的使用

一、什么是EnumSet? EnumSet是用于枚举类的专用Set集合。 它实现了Set接口并且继承AbstractSet。 当计划使用EnumSet时,必须考虑以下几点: 1、它只能包含枚举值,并且所有值必须属于同一个枚举。 2、它不允许添加 null,在尝试这样做时会抛出NullPointerException。 3、它不…

【SpringCloud AlibabaSentinel实现熔断与限流】

本笔记内容为尚硅谷SpringCloud AlibabaSentinel部分 目录 一、Sentinel 1、官网 2、Sentinel是什么 3、下载 4、特性 5、使用 二、安装Sentinel控制台 1、sentinel组件由2部分构成 2、安装步骤 1.下载 2.运行命令 3.访问sentinel管理界面 三、初始化演示工程 …

KVM虚拟机的磁盘无损扩容方法-qcow2格式的

起因:我的KVM主机上安装了基于Debian11的 虚拟机母鸡,其他虚拟机都由此克隆而来。因为最初只配置了8G的虚拟硬盘,因此在需要占用比较大的空间的应用时,就比较麻烦。度娘等中文搜索结果没找到答案,只能google了。 这里…

JVM系统优化实践(16):线上GC案例(一)

您好,我是湘王,这是我的CSDN博客,欢迎您来,欢迎您再来~ 列举几个实际使用案例说一下GC的问题。一个高峰期每秒10万QPS的社交APP,个人主页模块是流量最大的那个,而一次个人主页的查询&#xff0c…

python文本自动伪原创-ai一键伪原创

chatgpt批量伪原创的优势 ChatGPT是一个由OpenAI开发的强大的自然语言处理模型,它具有批量伪原创的优势,以下是这些优势: 模型能够处理大量的数据:ChatGPT通过训练大规模的语言模型来生成伪原创文本。这个模型拥有一个庞大的语料…

MySQL:varchar与date类型互转,对接java数据类型String和Date

目录 问题现象: 问题分析: varchar 转 date : date 转 varchar: 解决方法: varchar 转 date : date 转 varchar: 问题现象: 今天在项目中遇到一个问题: 现象&…

将DataTable中的数据保存到Excel (二) 使用NPOI

文章目录 背景1 NPOI 简介2 使用NPOI2.1 创建一个简单的工作簿2.2 简单的读取内容2.3 将DataTable数据导出到Excel(NPOI)2.4 Excel(NPOI)导入到DataTable 3 NPOI 总结 背景 前面写过一篇DataTable导出到Excel的文章,使用的是Office COM组件进行导入导出&#xff0c…

第五章 法律规范

目录 第一节 法律规则 一、法律规范与法律规则的概念辨析二、法律规则的逻辑结构 (一)假定:(二)行为模式:(三)法律后果: 三、法律规则与法律条文的关系 (想法…

【vue2】使用vue-admin-template动态添加路由的思路/addRoutes的使用

😉博主:初映CY的前说(前端领域) ,📒本文核心:用原生js实现省市区联动 【前言】在通用的后台管理项目的开发中,不仅仅是会涉及到对表单数据等的增删改查操作还会涉及到一些关于权限管理的问题。我们将基于一个RBAC的思维…

FPGA设计实战演练.高级技巧篇-----读书笔记

第一章 从PCB开始研究FPGA设计问题 一、PCB布线 1、要求 对所有器件进行电源滤波,均匀分配电源,降低系统噪声。 匹配信号线,减小信号反射。 降低并行走线之间的串扰。 减小地反弹效应。 进行阻抗匹配。 2、微带传输布局,走…

全景丨0基础学习VR全景制作,平台篇第六章:全局功能-开场提示

大家好欢迎观看蛙色平台使用教程 编辑器功能位置 1、功能说明 开场提示是指VR漫游作品加载好以后,进入到全景里面时,优先展示的图像。 PC端/移动端,均可设置起到指引用户的作用。 2、功能要用在哪? (1)场…

无人机影像处理流程

无人机由于其方便快捷,精度高等特点已经广泛应用于农田尺度的作物生长监测。尤其是近年来大疆推出了两个多光谱无人机,价格也相较便宜。但目前无人机的使用实际上需要进一步处理才能获取得到农田的基本信息,主要包括影像的校正和图像拼接&…

FME教程:GIS建筑面转CAD格式JMD,还原房屋建筑结构、层数、地物样式,shp转CAD,GIS转dwg

GIS数据转CAD数据,是经常遇到的需求,但是CAD数据形式与GIS相差甚远,因此GIS转CAD后,要还原图形样式和地物属性便成为了一个难点。 今天介绍使用FME进行shp格式房屋面数据转dwg格式的JMD图层的方法。实现房屋的地物样式、结构、层…

Android studio Activity启动模式

1.四种启动模式: 1).standard(标准模式) 特点:1.Activity的默认启动模式 2.每启动一个Activity就会在栈顶创建一个新的实例。例如:闹钟程序 缺点:当Activity已经位于栈顶时…

C#模拟实现输出进销存管理系统中的每月销售明细(实验五)

实验五:模拟实现输出进销存管理系统中的每月销售明细 任务要求: 运行程序,输入要查询的月份,如果输入的月份正确,则显示本月商品销售明细;如果输入的月份不存在,则提示“该月没有销售数据或者…