用GoConvey编写单元测试的一些总结
一、尽量用Convey将所有测试用例的Convey汇总
用Convey嵌套的方法,将所有测试用例的Convey用一个大的Convey包裹起来,每个测试函数下只有一个大的Convey。比如下面的示例代码:
import ("testing". "github.com/smartystreets/goconvey/convey"
)func TestStringSliceEqual(t *testing.T) {Convey("TestStringSliceEqual", t, func() {Convey("should return true when a != nil && b != nil", func() {a := []string{"hello", "goconvey"}b := []string{"hello", "goconvey"}So(StringSliceEqual(a, b), ShouldBeTrue)})Convey("should return true when a == nil && b == nil", func() {So(StringSliceEqual(nil, nil), ShouldBeTrue)})Convey("should return false when a == nil && b != nil", func() {a := []string(nil)b := []string{}So(StringSliceEqual(a, b), ShouldBeFalse)})Convey("should return false when a != nil && b != nil", func() {a := []string{"hello", "world"}b := []string{"hello", "goconvey"}So(StringSliceEqual(a, b), ShouldBeFalse)})})
}
这样做的好处是,看单测结果更为清晰直观:
=== RUN TestStringSliceEqualTestStringSliceEqual should return true when a != nil && b != nil ✔should return true when a == nil && b == nil ✔should return false when a == nil && b != nil ✔should return false when a != nil && b != nil ✔4 total assertions--- PASS: TestStringSliceEqual (0.00s)
PASS
ok infra/alg 0.006s
二、用GWT结构来描述复杂的测试用例
GWT结构嵌套了三层Convey:最外层是Given层,用来给定测试用例需要的数据;中间一层是When层,用来执行被测试的函数方法,得到result;最内层是Then层,用So来对result进行断言,看结果是否满足期望。
1 示例代码
示例代码如下:
func TestStringSliceEqualIfBothNil(t *testing.T) {Convey("Given two string slice which are both nil", t, func() {var a []string = nilvar b []string = nilConvey("When the comparision is done", func() {result := StringSliceEqual(a, b)Convey("Then the result should be true", func() {So(result, ShouldBeTrue)})})})
}func TestStringSliceNotEqualIfNotBothNil(t *testing.T) {Convey("Given two string slice which are both nil", t, func() {a := []string(nil)b := []string{}Convey("When the comparision is done", func() {result := StringSliceEqual(a, b)Convey("Then the result should be false", func() {So(result, ShouldBeFalse)})})})
}func TestStringSliceNotEqualIfBothNotNil(t *testing.T) {Convey("Given two string slice which are both not nil", t, func() {a := []string{"hello", "world"}b := []string{"hello", "goconvey"}Convey("When the comparision is done", func() {result := StringSliceEqual(a, b)Convey("Then the result should be false", func() {So(result, ShouldBeFalse)})})})
}
在实际运用中,可以结合第一条方法构成四层嵌套来描述一个测试用例:
func TestStringSliceEqual(t *testing.T) {Convey("TestStringSliceEqualIfBothNotNil", t, func() {Convey("Given two string slice which are both not nil", func() {a := []string{"hello", "goconvey"}b := []string{"hello", "goconvey"}Convey("When the comparision is done", func() {result := StringSliceEqual(a, b)Convey("Then the result should be true", func() {So(result, ShouldBeTrue)})})})})Convey("TestStringSliceEqualIfBothNil", t, func() {Convey("Given two string slice which are both nil", func() {var a []string = nilvar b []string = nilConvey("When the comparision is done", func() {result := StringSliceEqual(a, b)Convey("Then the result should be true", func() {So(result, ShouldBeTrue)})})})})Convey("TestStringSliceNotEqualIfNotBothNil", t, func() {Convey("Given two string slice which are both nil", func() {a := []string(nil)b := []string{}Convey("When the comparision is done", func() {result := StringSliceEqual(a, b)Convey("Then the result should be false", func() {So(result, ShouldBeFalse)})})})})Convey("TestStringSliceNotEqualIfBothNotNil", t, func() {Convey("Given two string slice which are both not nil", func() {a := []string{"hello", "world"}b := []string{"hello", "goconvey"}Convey("When the comparision is done", func() {result := StringSliceEqual(a, b)Convey("Then the result should be false", func() {So(result, ShouldBeFalse)})})})})}
2 大坑
注意!Given层中最好只有一个Then,因为多个Then会导致每执行完一个Then就会再次执行一遍被测试的函数方法,导致多次执行的结果可能并不相同从而导致意料之外的错误(比如上面示例中的“result := StringSliceEqual(a, b)”)。所以如果选择使用GWT的结构,那么就要保证W中只有一个T,最好也要保证G中只有一个W。
三、自定义断言函数
断言函数So中第二个参数Assertion类型定义:
type Assertion func(actual interface{}, expected ...interface{}) string
返回空字符串表示断言成功,否则就是断言失败了。
1 自定义断言函数
所以我们自定义断言函数时也要注意这点,下面是一个参考示例:
func ShouldSummerBeComming(actual interface{}, expected ...interface{}) string {if actual == "summer" && expected[0] == "comming" {return ""} else {return "summer is not comming!"}
}
上述代码中,第一个条件表示断言成功,其它所有情况都是断言失败。
2 在So中使用自定义的断言函数
func TestSummer(t *testing.T) {Convey("TestSummer", t, func() {So("summer", ShouldSummerBeComming, "comming")So("winter", ShouldSummerBeComming, "comming")})
}
测试结果:
=== RUN TestSummerTestSummer ✔✘Failures:* /Users/zhangxiaolong/Desktop/D/go-workspace/src/infra/alg/slice_test.go Line 52:summer is not comming!2 total assertions--- FAIL: TestSummer (0.00s)
FAIL
exit status 1
FAIL infra/alg 0.006s
相关文章:
用GoConvey编写单元测试的一些总结
一、尽量用Convey将所有测试用例的Convey汇总 用Convey嵌套的方法,将所有测试用例的Convey用一个大的Convey包裹起来,每个测试函数下只有一个大的Convey。比如下面的示例代码: import ("testing". "github.com/smartystreet…...
Linux Arm64修改页表项属性
文章目录 前言一、获取pte1.1 pgd_offset1.2 pud_offset1.3 pmd_offset1.4 pte_offset_kernel 二、修改pte属性2.1 set/clear_pte_bit2.2 pte_wrprotect2.3 pte_mkwrite2.4 pte_mkclean2.5 pte_mkdirty 三、set_pte_at四、__flush_tlb_kernel_pgtable五、demo参考资料 前言 在…...

elasticsearch14-高亮
个人名片: 博主:酒徒ᝰ. 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来。 本篇励志:三人行,必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》,SpringCloud…...

HUAWEI华为MateBook X Pro 2021款 i7 集显(MACHD-WFE9Q)原装出厂Win10系统20H2
华为笔记本电脑原厂系统自带指纹驱动、显卡驱动、声卡驱动、网卡驱动等所有驱动、出厂主题壁纸、系统属性华为专属LOGO标志、Office办公软件、华为电脑管家等预装程序 链接:https://pan.baidu.com/s/1oeSM0ciwyyRIKms5tR4SNA?pwdo2gq 提取码:o2gq...

21天学会C++:Day9----初识类与对象
CSDN的uu们,大家好。这里是C入门的第九讲。 座右铭:前路坎坷,披荆斩棘,扶摇直上。 博客主页: 姬如祎 收录专栏:C专题 目录 1. 面向过程与面向对象 2. 类的定义 3. 类中的访问限定符 3.1 访问限定符的…...

【深度学习】 Python 和 NumPy 系列教程(十七):Matplotlib详解:2、3d绘图类型(3)3D条形图(3D Bar Plot)
目录 一、前言 二、实验环境 三、Matplotlib详解 1、2d绘图类型 2、3d绘图类型 0. 设置中文字体 1. 线框图 2. 3D散点图 3. 3D条形图(3D Bar Plot) 一、前言 Python是一种高级编程语言,由Guido van Rossum于1991年创建。它以简洁、易读…...
基于Spring Boot+vue的酒店管理系统
文章目录 项目介绍主要功能截图:前台后台部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于Spring Boot+vue的酒店管理…...
Python 通过threading模块实现多线程
视频版教程 Python3零基础7天入门实战视频教程 我们可以使用threading模块的Thread类的构造器来创建线程 def _ init _(self, groupNone, targetNone, nameNone, args(), kwargsNone, *, daemonNone): 上面的构造器涉及如下几个参数。 group:指定该线程所属的线程组。目前该…...

用一个RecyclerView实现二级评论
先上个效果图(没有UI,将就看吧),写代码的整个过程花了4个小时左右,相比当初自己开发需求已经快了很多了哈。 给产品估个两天时间,摸一天半的鱼不过分吧(手动斜眼) 需求拆分 这种大家…...
音视频 SDL简介
一、SDL简介 SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Win…...

7.前端·新建子模块与开发(自动生成)
文章目录 学习地址视频笔记自动代码生成模式开发增删改查功能调试功能权限分配 脚本实现权限分配 学习地址 https://www.bilibili.com/video/BV13g411Y7GS/?p15&spm_id_frompageDriver&vd_sourceed09a620bf87401694f763818a31c91e 视频笔记 自动代码生成模式开发 …...

Linux 创建目录
语法:mkdir xxx Linux路径 在当前目录下创建文件夹 在/目录下创建文件夹 如果想要一次性创建多个层级的目录,如下图 会报错,因为上级目录test并不存在,所以无法创建test目录 可以通过-p选项,将一整个链条都创建完成…...
【DIY小记】修复Win10启动出现蓝屏0xc0000185错误的一些方法
近些日子想到自己尘封已久的笔记本电脑没有开机了,很多软件驱动之类的没有更新,就打算把电脑开起来做一轮批量升级。但开电脑的时候很久没有进入Win10桌面,等了很长一段时间蓝屏提示0xc0000185错误,说系统需要恢复。经历了一番折腾…...

Linux 下的 10 个 PDF 软件
本文[1]是我们正在进行的有关 Linux 顶级工具系列的延续,在本系列中,我们将向您介绍最著名的 Linux 系统开源工具。 随着互联网上越来越多地使用可移植文档格式 (PDF) 文件来获取在线书籍和其他相关文档,拥有 PDF 查看器/阅读器对于桌面 Linu…...
浅谈redis分布式锁
浅谈redis分布式锁 分布式锁介绍 分布式锁,顾名思义,分布式系统中的锁,当多个进程不在同一个系统中时,用分布式锁控制各个进程对共享资源的访问,通过互斥来保持一致性。 使用场景:电商中某商品的秒杀活动…...

【Python保姆级教程】List容器
文章目录 前言一、列表是什么二、列表的定义2.1 有初始值2.2 空列表使用方括号创建空列表使用list()函数创建空列表 三、list列表常用操作3.1 添加元素3.2 删除元素3.3 修改元素3.4 列表长度 四、遍历操作4.1 使用for循环4.2 使用while循环和索引 总结 前言 Python是一种广泛使…...

微服务保护-授权规则
个人名片: 博主:酒徒ᝰ. 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来。 本篇励志:三人行,必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》,SpringCloud…...
v-if失效原因
一般v-if失效都是和绑定变量有关,我所知道的一般有两种 1.绑定的变量为String类型或者其他类型 就是返回的变量类型与所需要的布尔类型不匹配。 <template><div><div id"container" ref"container" v-iftype></div>&l…...

Chrome 基于 Wappalyzer 查看网站所用的前端技术栈
1. 找到谷歌商店 https://chrome.google.com/webstore/search/wappalyzer?utm_sourceext_app_menu 2. 搜索 Wappalyzer 3. 添加至Chrome 4. 使用 插件 比如打开 https://www.bilibili.com/ 就可以看到其所以用的前端技术栈了...
python的装饰器
作用:在不改变原来函数的代码情况下,进行修改,或者增加函数的功能装饰器本质上就是一个闭包雏形:def wrapper(fn): wrapper: 装饰器 , fn: 目标函数def inner():# 在目标函数执行前的一些动作fn()# 在目标函数执行后的一些动作return inner #千万别加(),这里是返回一…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...