加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

GOLANG测试必须用带堆栈的errors

发布时间:2020-12-16 19:11:00 所属栏目:大数据 来源:网络整理
导读:原文:https://gocn.io/article/366 GOLANG测试时,可以用匿名对象填充测试序列,但是如果没有带堆栈的errors,那么会造成出现错误时无法排查。 先看测试序列的填充,参考tricks-2015这个文章,怕你翻不了墙,我把内容粘贴过来就是: Anonymous structs: tes

原文:https://gocn.io/article/366

GOLANG测试时,可以用匿名对象填充测试序列,但是如果没有带堆栈的errors,那么会造成出现错误时无法排查。

先看测试序列的填充,参考tricks-2015这个文章,怕你翻不了墙,我把内容粘贴过来就是:

Anonymous structs: test cases (1/2)

These properties enable a nice way to express test cases:

func TestIndex(t *testing.T) {
    var tests = []struct {
        s   string
        sep string
        out int
    }{
        {"","",0},{"","a",-1},{"fo","foo",{"foo",{"oofofoofooo","f",2},// etc
    }
    for _,test := range tests {
        actual := strings.Index(test.s,test.sep)
        if actual != test.out {
            t.Errorf("Index(%q,%q) = %v; want %v",test.s,test.sep,actual,test.out)
        }
    }
}

是的,看起来很方便,出错时也知道哪里的问题,但是实际上如果序列中有函数,那就悲剧了。让我们来试试,考虑一个包头的定义,它就是两个字段,然后序列化成[]byte

type MyHeader struct {
    Version uint8
    Size uint16
}

func (v MyHeader) MarshalBinary() ([]byte,error) {
    return []byte{byte(v.Version),0,0},nil // Failed.
}

为了测试设置不同的值,得到不同的字节,我们用两个函数来填充测试序列:

func TestMyHeader_MarshalBinary(t *testing.T) {
    mhs := []struct {
        set     func(h *MyHeader)
        compare func(p []byte) error
    }{
        {func(h *MyHeader) { h.Size = 1 },func(p []byte) error {
            if p[1] != 0x01 {
                return fmt.Errorf("p[1] is %v",p[1])  // line 194
            }
            return nil
        }},{func(h *MyHeader) { h.Size = 2 },func(p []byte) error {
            if p[1] != 0x02 {
                return fmt.Errorf("p[1] is %v",p[1])  // line 200
            }
            return nil
        }},}
    for _,mh := range mhs {
        h := &MyHeader{}
        mh.set(h)
        if b,err := h.MarshalBinary(); err != nil {
            t.Errorf("error is %+v",err)
        } else if err = mh.compare(b); err != nil {
            t.Errorf("invalid data,err is %+v",err) // line 211
        }
    }
}

结果我们就懵逼了,出现的错误行数都是在error那个地方211行是不够的,还需要知道是194还是200出问题了:

--- FAIL: TestMyHeader_MarshalBinary (0.00s)
    iprouter_test.go:211: invalid data,err is p[1] is 0
    iprouter_test.go:211: invalid data,err is p[1] is 0

怎么办呢?把堆栈信息带上,参考错误最佳实践,改成这样:

import oe "github.com/ossrs/go-oryx-lib/errors"

创建error时用这个package:

if p[1] != 0x01 {
                return oe.Errorf("p[1] is %v",p[1])  // line 194
            }
            if p[1] != 0x02 {
                return oe.Errorf("p[1] is %v",p[1])  // line 200
            }

结果可以看到详细的堆栈:

iprouter_test.go:211: invalid data,err is p[1] is 0
        _/Users/winlin/git/test/src/core.TestMyHeader_MarshalBinary.func4
            /Users/winlin/git/test/src/core_test.go:200
        _/Users/winlin/git/test/src/core.TestMyHeader_MarshalBinary
            /Users/winlin/git/test/src/core_test.go:210
        testing.tRunner
            /usr/local/Cellar/go/1.8.1/libexec/src/testing/testing.go:657
        runtime.goexit
            /usr/local/Cellar/go/1.8.1/libexec/src/runtime/asm_amd64.s:2197

这样可以嵌套非常多的函数做测试了。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读