3.2 单元测试-依赖

工程中复杂的项目,一般会依赖数据库、缓存等,而我们的单测需要保证稳定性和幂等性

稳定是指相互隔离,能在任何时间,任何环境,运行测试

幂等是指每一次测试运行都应该产生与之前一样的结果。而要实现这一目的就要用到mock机制

2月摸鱼计划08单元测试-依赖_单元测试

3.3 单元测试-文件处理

下面举个例子,打开文件读入 将文件中的第一行字符串中的11替换成00,执行单测,测试通过,而我们的单测需要依赖本地的文件,如果文件被修改或者删除测试就会fail

为了保证测试case的稳定性,我们对读取文件函数进行mock,屏蔽对于文件的依赖

2月摸鱼计划08单元测试-依赖_单元测试_02

3.4 单元测试-Mock

monkey是一个开源的mock测试库,可以对method,或者实例方法的方法进行mock(打桩)

打桩指的是:用一个函数A 替换函数B,B作为原函数;A作为打桩函数

Mock Patch(原函数,需要打桩的函数) 的作用域在 Runtime;

Unpatch(打桩函数):打桩结束后把原函数卸载掉

monkey主要是在运行时通过 Go 的 unsafe 包,能够将内存中函数的地址替换为运行时函数的地址,在测试中调用的就是运行时的打桩函数B地址。

2月摸鱼计划08单元测试-依赖_单元测试_03

下面是一个mock的使用样例,通过patch对Readfineline进行打桩mock,默认返回line110,这里通defer卸载mock,这样整个测试函数就摆脱了本地文件的束缚和依赖

2月摸鱼计划08单元测试-依赖_基准测试_04

3.5 基准测试

Go 语言还提供了基准测试框架,基准测试是指测试一段程序的运行性能及耗费 CPU 的程度

而我们在实际项目开发中,经常会遇到代码性能瓶颈,为了定位问题经常要对代码做性能分析,这就用到了基准测试。使用方法类似于单元测试,

2月摸鱼计划08单元测试-依赖_服务器_05

3.5.1 基准测试-例子

这里举一个服务器负载均衡的例子,首先我们有10个服务器列表,每次随机(rand包)执行select函数随机选择一个执行。

2月摸鱼计划08单元测试-依赖_服务器_06

3.5.2 基准测试-运行

基准测试以Benchmark开头,入参是testing.B, 用b中的N值反复递增循环测试(对一个测试用例的默认测试时间是 1 秒,当测试用例函数返回时还不到 1 秒,那么 testing.B 中的 N 值将按 1、2、5、10、20、50……递增,并以递增后的值重新进行用例函数测试

Resttimer重置计时器,我们在reset之前做了init或其他的准备操作,这些操作不应该作为基准测试的范围

runparallel()函数是多协程并发测试;执行 2个基准测试,发现代码在并发情况下存在劣化,主要原因是rand为了保证全局的随机性和并发安全,持有了一把全局锁

2月摸鱼计划08单元测试-依赖_单元测试_07

3.5.3 基准测试-优化

https://github.com/bytedance/gopkg

而为了解决这一随机函数性能问题,开源了一个高性能随机数方法fastrand,上面有开源地址;我们这边再做一下基准测试,性能提升百倍。主要的思路是牺牲了一定的数列的一致性,在大多数场景是适用的,同学在后面遇到随机的场景可以尝试用一下。

2月摸鱼计划08单元测试-依赖_单元测试_08