Go:测试框架GoConvey 简介
快速开始
GoConvey是一个完全兼容官方Go Test的测试框架,一般来说这种第三方库都比官方的功能要强大、更加易于使用、开发效率更高,闲话少说,先看一个example:
package utils
import (. "github.com/smartystreets/goconvey/convey""testing"
)func TestSpec(t *testing.T) {Convey("Given some integer with a starting value", t, func() {x := 1Convey("When the integer is incremented", func() {x++Convey("The value should be greater by one", func() {So(x, ShouldEqual, 2)})})})
}
看着复杂, 一层层的嵌套,如果你使用IDE的话你可以点到源码里面看一下其方法注释,其实已经说的非常清楚了,这里摘取部分看一下:
// Convey is the method intended for use when declaring the scopes of
// a specification. Each scope has a description and a func() which may contain
// other calls to Convey(), Reset() or Should-style assertions. Convey calls can
// be nested as far as you see fit.
//
// IMPORTANT NOTE: The top-level Convey() within a Test method
// must conform to the following signature:
//
// Convey(description string, t *testing.T, action func())
//
// All other calls should look like this (no need to pass in *testing.T):
//
// Convey(description string, action func())
这个用法相对简单了,Convey定义了一个局部的作用域,在这个作用域里面我们可以定义变量,调用方法,然后重复继续这个操作,low-level的Convey会继承top-level的变量。
了解之后,我们来扩展一下这个例子:
func TestSpec(t *testing.T) {Convey("Given some integer with a starting value", t, func() {x := 1y := 10Convey("When the integer is incremented", func() {x++Convey("The value should be greater by one", func() {So(x, ShouldEqual, 2)})})Convey("When x < y", func() {if x < y {x = x + ySo(x, ShouldBeGreaterThan, y)}})})
}
非常简单,当然这里我们并没有测试任何函数或方法,下面咱们写一个函数真正测试一下,假设有下面的方法:
func Div(a, b int) (int, error) {if b == 0 {return 0, errors.New("can not div zero")}return a / b, nil
}
使用GoConvey的话,测试代码可以这么写:
func TestDiv(t *testing.T) {const X = 10Convey("Normal Result", t, func() {res, err := Div(X, 2)So(res, ShouldEqual, 5)So(err, ShouldBeNil)Convey("Extend Scope", func() {res, err := Div(res, 2)So(res, ShouldEqual, 2)So(err, ShouldBeNil)})})Convey("Error Result", t, func() {res, err := Div(X, 0)So(res, ShouldEqual, 0)So(err, ShouldNotBeNil)})
}
有人可能会觉得这和官方的没多大区别,相当于多加了一个注释,可以对每一个测试用例标识,但是不仅仅如此,这个库还提供了大量增强的Assertions,可以非常方便的对字符串、slice、map结果进行断言测试,具体的话可以查看一下文档或者点进去看看源码注释,这些源码注释基本上已经写的非常清楚了。
Web UI
此外,框架还提供了一个Web端的UI界面,可以非常方便的查看测试覆盖和运行情况,还可以自动运行测试,执行goconvey命令就可以启动服务,快试一试吧!(虽然说像Goland这样的IDE也提供了GUI工具查看测试覆盖率,但是这个更加方便)
另外,这个框架还提供了自定义Assertions的功能,使用起来也很方便,有一个通用的模板:
func should<do-something>(actual interface{}, expected ...interface{}) string {if <some-important-condition-is-met(actual, expected)> {return "" // empty string means the assertion passed}return "<some descriptive message detailing why the assertion failed...>"
}
举个例子,这里定义一个试试:
func shouldNotGreatThan100(actual interface{}, expected ...interface{}) string {if actual.(int) > 100 {return "too big than 100"} else {return ""}
}
定义通用的逻辑
有时候测试会需要做一些准备工作,而且是重复的,比如说一些初始化操作,这时候就可以定义一个函数完成这件事,不必每次测试重复做,官方文档里面举了一个数据库测试的例子,每次测试前开启事务,测试结束后回滚事务,这里贴一下官方的example,大家看一下,很容易理解:
package main
import ("database/sql""testing"_ "github.com/lib/pq". "github.com/smartystreets/goconvey/convey"
)
func WithTransaction(db *sql.DB, f func(tx *sql.Tx)) func() {return func() {tx, err := db.Begin()So(err, ShouldBeNil)Reset(func() {/* Verify that the transaction is alive by executing a command */_, err := tx.Exec("SELECT 1")So(err, ShouldBeNil)tx.Rollback()})/* Here we invoke the actual test-closure and provide the transaction */f(tx)}
}
func TestUsers(t *testing.T) {db, err := sql.Open("postgres", "postgres://localhost?sslmode=disable")if err != nil {panic(err)}Convey("Given a user in the database", t, WithTransaction(db, func(tx *sql.Tx) {_, err := tx.Exec(`INSERT INTO "Users" ("id", "name") VALUES (1, 'Test User')`)So(err, ShouldBeNil)Convey("Attempting to retrieve the user should return the user", func() {var name stringdata := tx.QueryRow(`SELECT "name" FROM "Users" WHERE "id" = 1`)err = data.Scan(&name)So(err, ShouldBeNil)So(name, ShouldEqual, "Test User")})}))
}
/* Required table to run the test:
CREATE TABLE "public"."Users" ( "id" INTEGER NOT NULL UNIQUE, "name" CHARACTER VARYING( 2044 ) NOT NULL
);
*/
相关文章:

Go:测试框架GoConvey 简介
快速开始 GoConvey是一个完全兼容官方Go Test的测试框架,一般来说这种第三方库都比官方的功能要强大、更加易于使用、开发效率更高,闲话少说,先看一个example: package utils import (. "github.com/smartystreets/goconvey…...

JavaWeb-特殊文件(propertis与XML)
目录 Properties文件 一.properties介绍 二.properties使用 三.解决中文乱码问题 XML文件 一.XML介绍 二.XML文件的语法规则 三.XML的使用 Properties文件 一.properties介绍 1.什么是properties文件 Properties文件是一种常用的配置文件格式,用于存储键值…...

ffmpeg合并mp4视频文件
下载ffmpeg Download FFmpeg 2配置环境 右键此电脑-》属性-》高级系统设置 环境变量-》path 解压上面ffmpeg压缩包,找到bin目录,复制完整路径,添加到path环境变量中 测试ffmpeg ffmpeg合并MP4文件 创建一个文本文件,例如inpu…...

ATF BL1/BL2 ufs_read_blocks/ufs_write_blocks使用分析
ATF BL1/BL2 ufs_read_blocks/ufs_write_blocks使用分析 1 ATF的下载链接2 ATF BL1/BL2 ufs_read_blocks/ufs_write_blocks处理流程2.1 ATF BL1/BL2 ufs_read_blocks2.2 ATF BL1/BL2 ufs_write_blocks 3 UFS System Model4 ufs_read_blocks/ufs_write_blocks详细分析4.1 ufs_re…...

Elasticsearch(十二)搜索---搜索匹配功能③--布尔查询及filter查询原理
一、前言 本节主要学习ES匹配查询中的布尔查询以及布尔查询中比较特殊的filter查询及其原理。 复合搜索,顾名思义是一种在一个搜索语句中包含一种或多种搜索子句的搜索。 布尔查询是常用的复合查询,它把多个子查询组合成一个布尔表达式,这些…...

解决Windows下的docker desktop无法启动问题
以管理员权限运行cmd 报错: docker: error during connect: Post http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.40/containers/create: open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuration on Windows,…...

LLM生成式 AI 项目生命周期Generative AI project lifecycle
在本课程的其余部分中,您将学习开发和部署LLM驱动应用所需的技巧。在这个视频中,您将了解一个能帮助您完成此工作的生成式AI项目生命周期。此框架列出了从构思到启动项目所需的任务。到课程结束时,您应该对您需要做的重要决策、可能遇到的困难…...
java高并发系列 - 第13天:JUC中的Condition对象
java高并发系列 - 第13天:JUC中的Condition对象 java高并发系列第13篇文章 本文内容 synchronized中实现线程等待和唤醒Condition简介及常用方法介绍及相关示例使用Condition实现生产者消费者使用Condition实现同步阻塞队列Object对象中的wait(),notify()方法,用于线程等待…...
【TTY子系统】printf与printk深入驱动解析
tty子系统解析 tty子系统是一个庞大且复杂,也是内核维护者所头大的子系统。 At a first glance, the TTY layer wouldn’t seem like it should be all that challenging. It is, after all, just a simple char device which is charged with transferring byte-o…...

无涯教程-PHP - 全局变量函数
全局变量 与局部变量相反,可以在程序的任何部分访问全局变量。通过将关键字 GLOBAL 放置在应被识别为全局变量的前面,可以很方便地实现这一目标。 <?php$somevar15;function addit() {GLOBAL $somevar;$somevar;print "Somevar is $somevar";}addit(); ?> …...

shell脚本之循环语句
循环语句 循环含义 将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件 for循环语句 一般知道循环次数使用for循环 第一类 格式1: for名称 in 取值次数;do;done; 格式2: for 名称 in {取值列表} do done# 打印20次 for i i…...

派森 #P122. 峰值查找
描述 给定一个长度为n的列表nums,请你找到峰值并返回其索引。数组可能包含多个峰值,在这种情况下,返回任何一个所在位置即可。 (1)峰值元素是指其值严格大于左右相邻值的元素。严格大于即不能有等于; &…...
基础网络详解4--HTTP CookieSession 思考
一、cookie技术思考 一台多用户浏览器发起了三笔请求,将某款产品放入购物车中,A一次,选择了篮球;B两次,第一次选了足球,第二次选了钢笔。如何确认选择篮球、足球、钢笔的请求属于谁呢?如果不确认…...

14. 利用Canvas自制时钟组件
1. 说明 在自定义时钟组件时,使用到的基本控件主要是Canvas,在绘制相关元素时有两种方式:一种时在同一个canvas中绘制所有的部件元素,这样需要不断的对画笔和画布的属性进行保存和恢复,容易混乱;另一种就是…...

微信小程序使用云存储和Markdown开发页面
最近想在一个小程序里加入一个使用指南的页面,考虑到数据存储和减少页面的开发工作量,决定尝试在云存储里上传Markdown文件,微信小程序端负责解析和渲染。小程序端使用到一个库Towxml。 Towxml Towxml是一个可将HTML、Markdown转为微信小程…...

【C++】运算符重载 | 赋值运算符重载
Ⅰ. 运算符重载 引入 ❓什么叫运算符重载? 就是:运用函数,将现有的运算符重新定义,使其能满足各种自定义类型的运算。 回想一下,我们以前运算的对象是不是都是int、char这种内置类型? 那我们自定义的“…...
Python学习 -- 类对象从创建到常用函数
在Python编程中,类是一种强大的工具,用于创建具有共同属性和行为的对象。本篇博客将详细介绍Python中类和对象的创建,类的属性和方法,以及一些常用的类函数,通过丰富的代码例子来帮助读者深入理解。 一、类和对象的创…...

数组分割(2023省蓝桥杯)n种讨论 JAVA
目录 1、题目描述:2、前言:3、动态规划(bug):3、递归 剪枝(超时):4、数学(正解): 1、题目描述: 小蓝有一个长度为 N 的数组 A [A0, A1,…, AN−…...

很好的启用window10专业版系统自带的远程桌面
启用window10专业版系统自带的远程桌面 文章目录 启用window10专业版系统自带的远程桌面前言1.找到远程桌面的开关2. 找到“应用”项目3. 打开需要远程操作的电脑远程桌面功能 总结 前言 Windows操作系统作为应用最广泛的个人电脑操作系统,在我们身边几乎随处可见。…...

TCP定制协议,序列化和反序列化
目录 前言 1.理解协议 2.网络版本计算器 2.1设计思路 2.2接口设计 2.3代码实现: 2.4编译测试 总结 前言 在之前的文章中,我们说TCP是面向字节流的,但是可能对于面向字节流这个概念,其实并不理解的,今天我们要介…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...