golang的一些测试技巧和工具

大家好,我是李二狗!一起坚持!一起学习!
每日一课,无论长短,有所学有所得
业精于勤技在专,行则将至事必成

此前关于测试写过一篇内容一文搞定golang单元测试

今天这篇内容是对测试内容的补充,目录如下:

image

表格驱动测试

表格测试是一种编写更清晰的测试函数的方法;

顾名思义,表格驱动测试,就是指通过表格列举的方式来实现测试用例,表格中包含输入和预期输出,以及其他信息;这种方式是我们对测试的逻辑和思路更加清晰;

官方表格驱动测试的案例:

// fmt包中有如下一段测试代码:
// 定义测试的表格,包含了in输入字段和out期待输出字段
// 并且定义了该表格中的测试用例
// 然后使用t.Run的方式对每个用例进行测试
var flagtests = []struct {
    in  string
    out string
}{
    {"%a", "[%a]"},
    {"%-a", "[%-a]"},
    {"%+a", "[%+a]"},
    {"%#a", "[%#a]"},
    {"% a", "[% a]"},
    {"%0a", "[%0a]"},
    {"%1.2a", "[%1.2a]"},
    {"%-1.2a", "[%-1.2a]"},
    {"%+1.2a", "[%+1.2a]"},
    {"%-+1.2a", "[%+-1.2a]"},
    {"%-+1.2abc", "[%+-1.2a]bc"},
    {"%-1.2abc", "[%-1.2a]bc"},
}
func TestFlagParser(t *testing.T) {
    var flagprinter flagPrinter
    for _, tt := range flagtests {
        t.Run(tt.in, func(t *testing.T) {
            s := Sprintf(tt.in, &flagprinter)
            if s != tt.out {
                t.Errorf("got %q, want %q", s, tt.out)
            }
        })
    }
}

如果测试用例我们例举了非常多的话,我们希望测试用例可以并行执行,本身每个测试用例之间就是互不干扰的,因此上述代码可如下优化:

func TestFlagParser(t *testing.T) {
    var flagprinter flagPrinter
    for _, tt := range flagtests {
        ft := tt // 1. 重新声明变量,避免多个goroutine中使用了相同的变量
        t.Run(ft.in, func(t *testing.T) {
             t.Parallel()  // 2. 使用t.Parallel表示每个子测试之间能够彼此并行运行
            s := Sprintf(ft.in, &flagprinter)
            if s != ft.out {
                t.Errorf("got %q, want %q", s, ft.out)
            }
        })
    }
}

如上,既是表格驱动测试的用法;先定义表格以及测试用例,然后再通过t.Run子测试方式遍历表格;

自动生成表格驱动测试的代码gotests

gotests是一种自动生成表格驱动测试代码的工具;

使用案例:

  1. 比如在此前的一文搞定golang单元测试中,我们创建了split.go的业务文件;

  2. 安装gotests工具:$ go get -u github.com/cweill/gotests/...

  3. 执行命令:gotests -all -w split.go;关于gotests的命令参数,大家可以去官网学习一下;

    • -all:生成所有的测试函数和方法
    • -w:输出测试结果到文件而不是控制台
  4. 生成的测试代码的格式如下,我们需要在todo的位置添加我们的测试逻辑即可:

    package base_demo
    
    import (
     "reflect"
     "testing"
    )
    
    func TestSplit(t *testing.T) {
     type args struct {
         s   string
         sep string
     }
     tests := []struct {
         name       string
         args       args
         wantResult []string
     }{
         // TODO: Add test cases.
     }
     for _, tt := range tests {
         t.Run(tt.name, func(t *testing.T) {
             if gotResult := Split(tt.args.s, tt.args.sep); !reflect.DeepEqual(gotResult, tt.wantResult) {
                 t.Errorf("Split() = %v, want %v", gotResult, tt.wantResult)
             }
         })
     }
    }
    

go测试工具包--testfy

安装go get github.com/stretchr/testify;提供了更优雅的,灵活的,可mock的等等工具;

常用:testify/asserttestify/requiretestfy/mock

示例:

单元测试的时候,经常需要用到断言来检验测试结果,但是golang官方没有提供断言语法,导致我们可能会使用大量的ifelse语句;

testfy/assert为我们提供了很多常用的断言函数,让我们的测试代码实现的更加优雅;

比如在此前的一文搞定golang单元测试中我们检验TestSplit结果的方式如下:

if !reflect.DeepEqual(want, got) {
    t.Errorf("expected:%v, got:%v", want, got)
}

如果我们使用testfy/assert的话,就可以如下简化:

// t是testing.T
assert.Equal(t, want, got)  // 使用assert提供的断言函数;

//或者如下使用方式,先创建assert对象:
assert := assert.New(t)

assert.Equal(123, 123, "they should be equal")//是否相等测试
assert.NotEqual(123, 456, "they should not be equal")//是否不等测试
assert.Nil(object)//是否nil测试
if assert.NotNil(object) {
    assert.Equal("Something", object.Value)
}

testfy中除了assert工具以外,还有常用的是testfy/require工具,以及还提供了mockhttp的工具,大家可以去官网了解一下;

什么是mock呢?比如我们的测试中有一个步骤是向用户成功发送邮件,事实上我们需要用户确认邮件后,才认为该邮件用户已确认;但实际测试中,我们不可能真的给用户发送邮件,或者说我们不可能每次测试都真的发送邮件(假如不是邮件而是短信的话,每次测试可都是需要花钱的),因此mock就可以模拟用户确认短信的行为,即模拟功能;

mock技术可用于各种不同的系统,例如模拟数据库查询或者是与其他API的交互等等,非常实用;

关注李二狗 持续精进
坚持每日输出go开发+面试题+算法+工作经验等后端相关技术
关于我今年的计划请查看flag-2022
更多博客内容请查看bigshake
微信公众号李二狗的星球

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容