GOLANG测试必须用带堆栈的errors

原文: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", -1},
        {"foo", "foo", 0},
        {"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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

winlinvip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值