共计 5536 个字符,预计需要花费 14 分钟才能阅读完成。
download:2022 全面降级 Vue3+TS 仿知乎专栏企业级我的项目
Golang- 单元测试和模仿框架的介绍和举荐
简介: 摸索 golang 的单元测试框架,看看哪个框架与业务教训联合得更好。
我会在题目中标注举荐帧和不举荐帧。如果没有标注,阐明体验个别,然而没有特地的毛病。我将刮目相待。
一、单元测试框架介绍
1. 本地测试
1.1 示例
func TestModifyArr(t * 测试。T) {
arr := [3]int{0,1,2}
批改 (Arr)
if 112233 == arr[0] {
T.logf (“[testmodifyar] test 胜利批改了数组元素!”)
} else if 0 == arr[0] {
T.errorf (“[testmodifyar] test 未能批改数组元素!元素未修改”)
} 否则 {
T.errorf (“[testmodifyar] test 未能批改数组元素!未知元素:%d “,arr[0])
}
}
复制代码
留神: 在应用 t.Errorf 时,单个测试也会被设置为失败 (然而测试不会立刻进行,只有 FailedNow 或 Fatalf 才会进行)
1.2 扩大: 表格驱动的设计思维
其实就是把多个测试用例封装成一个数组,顺次执行同一个测试逻辑。
即便是其余测试框架,这种设计思路也是相当有用的,用例多的时候能够简化代码量。
示例:
危险值 (
pow tests =[] 构造 {
根底浮动 64
电源浮动 64
预期浮动 64
}{
{1, 5, 1},
{2, 4, 16},
{3, 3, 27},
{5, 0, 1},
}
)
// 测试一些数学包的计算方法
func testmathppkgmethodbytesting(t * testing。T) {
对于索引,以后测试:= 范畴功率测试 {
if currentTest.expected!= 数学。Pow(以后测试基准,以后测试功率){
t.errorf(“[TestMathPkgMethod]% d th test:%.2f % . 2f 的幂不是预期的:% . 2f “,
index,currentTest.base,currentTest.power,currentTest.expected)
}
}
t.Logf(“[TestMathPkgMethod] 所有测试都通过了!”)
}
复制代码
1.3 平行测试
应用办法: 在测试代码中执行:t.Parallel(),测试方法能够和其余测试用例并行执行。
场景: 个别须要同时执行多个用例,比方测试生产和生产。
但集体不倡议这么做,因为这有点违反“繁多测试”的概念: 繁多测试测试一个性能。相似的场景也能够通过在单次测量中设置通道多流程来实现。
2、goconvey
2.1 示例
介绍办法:
去找 github.com/smartystreets/goconvey/convey
导入模式:
导入(
。” github . com/smarty streets/go convey/convey “
)
// 揭示:goconvey、gomonkey 等工具类最好应用这种导入办法,缩小应用其外部办法的代码长度,使代码更加简洁。
复制代码
func TestMathPkgMethodByConvey(t * 测试。T) {
Convey(” Convey test power “,t,func() {
对于_,以后测试:= 范畴功率测试 {
所以 (数学。Pow(currentTest.base,currentTest.power),ShouldEqual,currentTest.expected)
}
})
}
复制代码
So 的这种办法构造对于刚接触 GoConvey 的同学来说可能有点难以了解。上面是源代码的简要阐明:
// 源代码:github . com \ smarty streets \ go convey @ v 1 . 6 . 4 \ convey \ context . go
类型断言函数 (理论接口{},应为 … 接口{}) 字符串
……
func (ctx *context) So(理论接口{},assert 断言,应为 … 接口{}) {
if result := assert(理论,预期 …);result == assertionSuccess {
ctx.assertionReport(报告。NewSuccessReport())
} 否则 {
ctx.assertionReport(报告。NewFailureReport(后果))
}
}
复制代码
要害是对 So 参数的了解。总共有三个参数:
理论: 输出
断言: 断言
预期: 预期值
通过查看定义,Assert assertion 实际上是一种办法,但事实上,Convey 包曾经帮忙咱们定义了大多数根本断言:
// 源代码:github . com \ smarty streets \ go convey @ v 1 . 6 . 4 \ convey \ assertions . go
危险值 (
ShouldEqual = 断言。肩平等
ShouldNotEqual = 断言。不应相等
ShouldAlmostEqual = 断言。应该差不多相等
ShouldNotAlmostEqual = 断言。ShouldNotAlmostEqual
should like = 断言。应该像
ShouldNotResemble = 断言。不应该类似
…..
复制代码
能够间接应用等于、大于或小于等判断办法。
2.2 双重嵌套
func TestMathPkgMethodByConvey(t * 测试。T) {
// 双重嵌套
Convey(“Convey test multiple test “,t,FailureHalts,func() {
Convey(“ 测试失败 ”,func() {
所以 (数学。Pow(5,2),ShouldEqual,26)
日志。printf(“[测试] 5^3 = 125?要执行!”)
所以(数学。Pow(5,3),ShouldEqual,125)
})
Convey(“ 胜利测试 ”,func() {
日志。printf(“[测试] 5^2 = 25?要执行!”)
所以 (数学。Pow(5,2),ShouldEqual,25)
})
})
}
复制代码
留神: 不再须要将测试对象增加到传送带的内层。
留神: 子传送的执行策略是并行的,因而前一个子传送的失败不会影响后续的传送。然而一个孩子被间断处决。
2.3 跳过测试
如果在这次提交中有些测试没有被齐全测试,您能够应用 TODO+ 首先跳过这些测试,首先进行正文,而后在下一次提交时改良它们。
SkipConvey: 跳过以后考察下的所有测试。
SkipSo: 跳过以后断言
2.4 设置失败后的执行策略
默认状况下,一个 Convey 下的多个 So 断言是失败后终止的策略。如果要调整,只需将失败策略增加到 Convey 参数中即可。例如,如果设置失败,请持续,而后应用失败持续。
// 源代码:github . com \ smarty streets \ go convey @ v 1 . 6 . 4 \ convey \ doc . go
常量 (
……
失败持续失败模式 = “ 持续 ”
……
故障暂停故障模式 = “ 暂停 ”
……
失败继承失败模式 = “ 继承 ”
)
复制代码
然而,应该留神,这里的故障后策略是针对一个传送下的多个 So 断言,而不是一个传送下的多个子传送。那么接下来咱们就来说说 Convey 的实现机制: 它是并行的。
2.5 子传送并发执行原理简介
在 go transportation 的底层,应用 jtolds/gls 库实现对 goroutine 的治理和多个子传输的并发执行。
// 源代码:github . com \ smarty streets \ go convey @ v 1 . 6 . 4 \ convey \ context . go
func (ctx *context)传送(我的项目 … 接口{}) {
……
if inner_ctx.shouldVisit() {
ctxMgr。设置值(gls。值{nodeKey: inner_ctx},func() {
// 条目。Func 是理论的测试方法。
inner _ ctx.conveyInner(条目。状况,进入。Func)
})
}
}
// 源代码:github . com \ jtolds \ gls @ v 4 . 20 . 0+ 不兼容 \context.go
func(m * context manager)set Values(new _ Values Values,context_call func()) {
……
// 此办法将确定是否满足并发执行的条件。
EnsureGoroutineId(func(GID uint){
…….// 解析传入的上下文参数。
context_call()
})
}
复制代码
常识无限,这里就不说 gls 库的原理了。借助一些文档,我晓得 gls 其实是通过 go 底层的 api 来治理 GPM 模型的,在满足肯定条件的状况下,会将子考察提交给子协同流程执行 (默认)。
如果你对 gls 库感兴趣,想晓得它的底层是如何治理合作流程的,能够参考:
Gl 官网 github 地址
gls godoc
3. 作证(举荐)
其实 evidence 的用法和 native testing 差不多,都是对断言的明确定义。
它提供了 assert 和 require 两种用法,别离对应失败后的执行策略。前者失败后继续执行,后者失败后立刻进行。但都是单断言失败,以后测试失败。
func TestGetStudentById(t * testing。T) {
currentMock := gomonkey。ApplyFunc(dbresource。NewDBController,dbresource。NewDBMockController)
推延以后时钟。重置 ()
学校服务。新学校服务 ()
学生:= 学校服务。GetStudentById(“1 “)
断言。NotEqual(t,“”,学生。姓名)
要求。Equal(t,studentsql。考试_学生_姓名,学生。姓名)
}
复制代码
4. 测试框架概述
上面简略总结一下几个测试框架: 集体感觉 GoConvey 的语法对于业务代码入侵来说有点重大,自身须要一些工夫去了解,比方 testify 的清晰逻辑。单元测试逻辑自身绝对简略。综上,更举荐应用 evident。
二。模仿框架介绍
1.gostub(不举荐)
1.1 根本用处
去找 github.com/prashantv/gostub
复制代码
func TestGetLocalIp(t * 测试。T) {
// 沉积变量
varStub := Stub(&testGlobalInt,100)
提早变量存根。重置 ()
日志。printf(“[测试模仿]模仿变量:%d “,testGlobalInt)
// 沉积办法
var getIpFunc = system。GetOutboundIP
funcStub := StubFunc(&getIpFunc,” 1.2.3.4 “)
提早 funcStub。重置 ()
}
复制代码
1.2 与 GoConvey 组合的示例
1.3 不举荐应用的起因
次要的限度太多了:
Gostub: 因为办法的 mock 要先申明变量能力被 mock,所以连贯口办法都须要这样定义,不是很不便。
此外,如果您须要一个 mock 办法,并且参数和返回的数量是可变长度的数组类型,您可能无奈定义 mock。
最初,同样的办法,如果须要模仿多个场景,gostub 无奈实现。这个很麻烦,mock 的不同参数场景应该算是 mock 的基本功能。
2、gomock
官网保护的 mock 框架,只有是对象 + 接口的数据结构,根本都能够通过 gomock 间接写不同场景的 mock。
之前写过一篇对于如何应用 gomock 的根底介绍。一般来说更适宜框架场景,比方 protobuf 定义生成的内部对象和接口。如果能主动生成 gomock 代码,开发起来会更不便。但不是特地适宜业务代码,因为业务外部往往定义了很多对象,为每个对象生成 mock 有点麻烦。
3.1 打桩办法
func TestGetAbsolutePath(t * 测试。T) {
// 打桩办法
funcStub := ApplyFunc(config。GetAbsolutePath,testGetAbsolutePath)
提早 funcStub。重置 ()
日志。Printf(“ 配置门路:%s “,config。GetAbsolutePath())
}
复制代码
总的来说和 gostub 的应用很像,就是办法要通过变量独自指定,mock 要设置。执行 ApplyFunc 办法
区别在于 StubFunc 间接定义方法的参数 (行为后果),而 ApplyFunc 还须要定义方法的具体动作(行为自身)。
3.2 用程序堆法。
func TestGetAbsolutePath(t * 测试。T) {
// 办法序列重叠
retArr:=[] 输入单元格{
{Values: Params{“。/testpath1”}},
{Values: Params{“。/testpath2”}},
{Values: Params{“。/testpath3”},次数:2,
}
ApplyFuncSeq(配置。GetAbsolutePath,retArr)
日志。Printf(“ 配置门路:%s “,config。GetAbsolutePath())
日志。Printf(“ 配置门路:%s “,config。GetAbsolutePath())
日志。Printf(“ 配置门路:%s “,config。GetAbsolutePath())
日志。Printf(“ 配置门路:%s “,config。GetAbsolutePath())
}
复制代码
3.3 全局变量的打桩
用法相似于 gostub 的 Stub 办法,不赘述。
此外,还有 ApplyMethod(为对象的指定办法打桩)、ApplyMethodSeq 等。,而且用法还是很像 ApplyFunc 的。您能够具体浏览参考博客,或者只查看源代码中的测试示例。
四。总结与瞻望
介绍了几种常见的单测和 mock 框架的应用办法,得出了 evidence+gomonkey 是一种比拟直观易用的框架的论断。