duanhao7786 2013-03-01 00:29
浏览 55
已采纳

Golang中的测试命名约定

I'm trying to unit test a Go package for the first time, and I have a couple of errors in the same file.

type FooErr int
type BarErr int

func (e *FooErr) Error () string {
    return "A Foo Error has occurred"
}

func (e *BarErr) Error () string {
    return "A Bar Error has occurred"
}

However, all naming conventions seem to look like this func TestXxx(*testing.T) (from the testing package documentation). This would mean my testing file would look like this:

func TestError (t *testing.T) { ... } // FooErr
func TestError (t *testing.T) { ... } // BarErr

Which is obviously two functions of the same signature. What is the recommended method for handling this?

  • 写回答

4条回答 默认 最新

  • douzhongjian0752 2013-03-02 02:39
    关注

    There are a few things to consider here:

    Errors

    Package-level exported error values are typically named Err followed by something, for instance ErrTimeout here. This is done so that clients of your package can do something like

    if err := yourpkg.Function(); err == yourpkg.ErrTimeout {
      // timeout
    } else if err != nil {
      // some other error
    }
    

    To facilitate this, they are often created either with errors.New:

    // Error constants
    var (
      ErrTimeout = errors.New("yourpkg: connect timeout")
      ErrInvalid = errors.New("yourpkg: invalid configuration")
    )
    

    or with a custom, unexported type:

    type yourpkgError int
    
    // Error constants
    var (
      ErrTimeout yourpkgError = iota
      ErrSyntax
      ErrConfig
      ErrInvalid
    )
    
    var errText = map[yourpkgError]string{
      ErrTimeout: "yourpkg: connect timed out",
      ...
    }
    
    func (e yourpkgError) Error() string { return errText[e] }
    

    One advantage of the latter approach is that it cannot compare equal with a type from any other package.

    In the case where you need some extra data inside the error, the name of the type ends in Error:

    type SyntaxError struct {
      File           string
      Line, Position int
      Description    string
    }
    
    func (e *SyntaxError) Error() string {
      return fmt.Sprintf("%s:%d:%d: %s", e.File, e.Line, e.Position, e.Description)
    }
    

    which, in contrast to the previous equality check, requires a type assertion:

    tree, err := yourpkg.Parse(file)
    if serr, ok := err.(*SyntaxError); ok {
      // syntax error
    } else if err != nil {
      // other error
    }
    

    In either case, it is important to document your code so that users of your package understand when they will be used and what functions might return them.

    Tests

    Tests are often named after the unit that they're testing. In many cases, you won't test error conditions separately, so TestError is not a name that should come up very often. The name of the test itself merely has to be unique, however, and is not constrained to match anything in the code under test in the same way that examples are. When you're testing multiple conditions of a piece of code, it is often best to formulate the test as a Table Driven Test. That wiki page has some good examples, but to demonstrate error checking, you might do this:

    func TestParse(t *testing.T) {
      tests := []struct{
        contents string
        err      error
      }{
        {"1st", nil},
        {"2nd", nil},
        {"third", nil},
        {"blah", ErrBadOrdinal},
        {"", ErrUnexpectedEOF},
      }
      for _, test := range tests {
        file := strings.NewReader(test.contents)
        if err := Parse(file); err != test.err {
          t.Errorf("Parse(%q) error %q, want error %q", test.contents, err, test.err)
        }
        // other stuff
      }
    }
    

    If you do need a special test function for a unit that does something weird and doesn't fit in the main test, you'd typically name it something descriptive like TestParseTimeout that includes both the unit and the behavior you're testing.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 Matlab怎么求解含参的二重积分?
  • ¥15 苹果手机突然连不上wifi了?
  • ¥15 cgictest.cgi文件无法访问
  • ¥20 删除和修改功能无法调用
  • ¥15 kafka topic 所有分副本数修改
  • ¥15 小程序中fit格式等运动数据文件怎样实现可视化?(包含心率信息))
  • ¥15 如何利用mmdetection3d中的get_flops.py文件计算fcos3d方法的flops?
  • ¥40 串口调试助手打开串口后,keil5的代码就停止了
  • ¥15 电脑最近经常蓝屏,求大家看看哪的问题
  • ¥60 高价有偿求java辅导。工程量较大,价格你定,联系确定辅导后将采纳你的答案。希望能给出完整详细代码,并能解释回答我关于代码的疑问疑问,代码要求如下,联系我会发文档