golang分层测试之单元测试-testing使用

前言

  • 基本上每一种高级计算机语言都有自己的代码逻辑测试的方式,也就是单元测试,其对于高级计算机语言的重要程度,大家在学习其他计算机语言的时候都有所了解,golang的单元测试,自身提供的testing package能够满足基本的测试需求,当然还有丰富API的第三方开源库,比如 gocheck,golang单元测试会分几篇文章来讲解,这次主要讲一下go语言使用testing做单元测试的一些方法

testing框架使用

  • Go语言通过内置库testing包提供自动化测试功能。包内测试只要运行命令 go test,就能自动运行符合规则的测试函数

示例代码

package hello
import "testing"

func TestHelloWorld(t *testing.T) {
    t.Log("hello world")
}
  • 说下golang编写测试代码的规范:
  1. 每个测试文件必须以 _test.go 结尾,并使用go test命令执行测试模块,否则golang无法识别出测试模块
  2. 作为测试模块文件,必须导入testing包
  3. 功能测试方法必须以 Test 开头,一般是接被测方法的名字,如TestAdd,但不强制
  4. 测试用例会按照源代码中写的顺序依次执行
  5. 测试方法TestXxx()的参数是testing.T,用于收集记录测试结果
  6. testing中的断言需要自己编写,通过在方法中通过调用testing.TError, Errorf, FailNow, Fatal, FatalIf方法来进识别测试通过与否,调用Log方法用来记录测试的信息

命令行

  • 单元测试使用 go test 命令启动
go test [-c] [-i] [build flags] [packages] [flags for test binary]
  • 例如:
$ go test -v helloworld_test.go
=== RUN   TestHelloWorld
--- PASS: TestHelloWorld (0.00s)
        helloworld_test.go:8: hello world
PASS
ok          command-line-arguments        0.004s
  • 下面是go test的一些常用传参方式
go test //默认执行当前目录下以xxx_test.go的测试文件
go test -v //可以看到详细的输出信息。
go test -v xxx_test.go //指定测试单个文件,但是该文件中如果调用了其它文件中的模块会报错
go test -v xxx_test.go xxx.go //指定测试单个文件和被测文件
go test -v -test.run Testxxx //指定某个测试函数运行,注意点是函数会用Testxxx去匹配所有包含Testxxx字符串作方法名的方法
go test -v -cover //显示覆盖的声明程度
  • 当然还有其他例如用来做压力测试的bench参数,这个在后续的文章中讲解

实战应用

  • 废话少说,我们直接用demo代码来讲解
    待测模块 demo.go
//demo by terrychow
package main
import "fmt"

func Add(x,y int) int   
{
return x+y
}

func main(){
  z:=Add(1,2)
  fmt.Print(z)
}
  • 待测模块demo.go是一个简单的加法方式Add,这个也是本次测试的待测方法
  • 由于待测模块demo.go为文件名,测试模块文件名必须以 _test 结尾,可命名为demo_test.go,不强制于被测文件前置同名,即可为other_test.go,测试模块文件路径可随意

测试模块 demo_test.go

//demo_test by terrychow
package main
import "testing"

func  TestAdd(t *testing.T) {
    s:=Add(1,2)
    if s!=3{
        t.Error("Expected 3, got ", s)
    }
    
}
  • 依照测试代码规范,我们编写出测试代码模块,然后使用go test命令来执行
go test demo_test.go demo.go -v -cover
  • 输出为
=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
PASS
coverage: 33.3% of statements
ok      command-line-arguments  0.613s  coverage: 33.3% of statements
  • 调整一下代码断言值
//demo_test by terrychow
package main
import "testing"

func  TestAdd(t *testing.T) {
    s:=Add(1,2)
    if s!=4{//此处修改了错误的返回
        t.Error("Expected 4, got ", s)
    }
    
}
  • 输出FAIL信息
=== RUN   TestAdd
--- FAIL: TestAdd (0.00s)
    demo_test.go:8: Expected 4, got  3
FAIL
coverage: 33.3% of statements
FAIL    command-line-arguments  0.668s
  • 一个基于golang内置的测试框testing的单元测试已经实现了

进阶玩法

  • 有时候我们针对一个方法的测试,会结合如路径覆盖、条件覆盖和语句覆盖等测试思路来进行对测试数据的组合测试,利用不同的数据组合验证覆盖方式,于是就有了组合测试的方式,针对Add方法,我们假设组合:
    1. 两个正数相加
    2. 两个负数相加
    3. 一正一负相加

示例代码

//demo by terrychow
package main
import "testing"

func TestGroupAdd(t *testing.T){
    var testdata=[] struct{
     arg1 int
     arg2 int
     sum int
}{
    {1,1,2},
    {-1,-1,-2},
    {-1,1,0},
}
    for _, test:=range testdata{
    sum:=Add(test.arg1,test.arg2)
    if sum!=test.sum{
    t.Errorf("arg1 %v and arg2 %v not except sum %v",test.arg1,test.arg2,test.sum)
    }
    }
}
  • 输出结果为
=== RUN   TestGroupAdd
--- PASS: TestGroupAdd (0.00s)
PASS
coverage: 33.3% of statements
ok      command-line-arguments  0.583s  coverage: 33.3% of statements
  • 假设其中一个为错误的数据,如
package main
import "testing"

func TestGroupAdd(t *testing.T){
    var testdata=[] struct{
     arg1 int
     arg2 int
     sum int
}{
    {1,1,2},
    {-1,-1,-1},//此处的sum为错误值
    {-1,1,0},
}
    for _, test:=range testdata{
    sum:=Add(test.arg1,test.arg2)
    if sum!=test.sum{
    t.Errorf("arg1 %v and arg2 %v not except sum %v",test.arg1,test.arg2,test.sum)
    }
    }
}
  • 输出FAIL信息
=== RUN   TestGroupAdd
--- FAIL: TestGroupAdd (0.00s)
    demo1_test.go:17: arg1 -1 and arg2 -1 not except sum -1
FAIL
coverage: 33.3% of statements
FAIL    command-line-arguments  0.688s
  • 会有对应的错误信息返回,说明错在哪一行

小结

  • testing作为go语言内置的测试库,其当然还不仅仅是做单元测试,之后讲解的API和UI自动化测试,以及后面的压力、性能测试也会使用到testing,足见其核心作用
  • 但testing也是有其限制性,没有良好的测试断言以及测试报告,靠使用者不断地写if else来判断显然麻烦,这也是下一篇文章要讲解go最常用单元测试框架gocheck,下回内容更精彩,请继续关注后续更新,谢谢大家
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249