【问题标题】:Error type checking in Go for unit table testsGo 中用于单元表测试的错误类型检查
【发布时间】:2014-06-15 22:05:36
【问题描述】:

我想根据预期结果的table test 测试返回的错误类型,如下所示:

var tabletest = []struct{
  instruction string
  want string
  err error
}{
  {"synonym for hi", "hello", nil}, // input, retval, errtype
  {"synonym for hig", "", TranslationError{}}, 
  {"sssnymm for hi", "", InstructionError{}},
}

func TestThesaurus(t *Testing) {
  for _, testcase := range tabletest {
    got, err := Thesaurus(testcase.instruction)
    // check error type
    // check result type
  }
}

在上面的示例中,根据发生的错误类型返回不同的错误子类。您可能会想象组成的 Thesaurus 函数的调用者会以不同的方式处理每种错误类型。

断言返回的错误类型和预期的错误类型相同的惯用方法是什么?

【问题讨论】:

    标签: unit-testing testing error-handling go


    【解决方案1】:

    使用type 开关。

    func TestThesaurus(t *Testing) {
      for _, testcase := range tabletest {
        got, err := Thesaurus(testcase.instruction)
    
        // Don't use && because we want to trap all cases where err is nil
        if err == nil  {
          if testcase.err != nil {
              // failure
          }
          continue
        }
    
        switch err.(type) {
        case TranslationError:
            if _,ok := (testcase.err).(TranslationError); !ok {
               // failure
            }
        case InstructionError:
            if _,ok := (testcase.err).(InstructionError); !ok {
               // failure
            }
        default:
            // Unrecognized error, failure
        }
    }
    

    它绝对不像reflect 那样简洁,但我认为它更Go-ish 和明确。

    【讨论】:

    • 这确实非常清楚可能会发生什么错误。如果真正调用它,我当然更愿意以这种方式处理该函数。不过,对于清晰性是否证明冗长是合理的,我仍然有两种看法。
    【解决方案2】:

    还有这个成语:

    在词库中...

    import "errors"
    
    var (
        TranslationError = errors.New("")
        InstructionError = errors.New("")
    )
    

    在测试用例中...

    if err != testcase.err {
    
    }
    

    但是,我认为在这个成语中,错误必须提前定义(即消息不能更改)。

    【讨论】:

      【解决方案3】:

      reflect.TypeOf 完成这项工作:

      import "reflect"
      
      ...
      
      func TestThesaurus(t *Testing) {
        for _, testcase := range tabletest {
          got, err := Thesaurus(testcase.instruction)
          // check error type
          if goterr, wanterr := reflect.TypeOf(err), reflect.TypeOf(testcase.err); 
               goterr != wanterr {
            t.Errorf("For instruction %q, unexpected error: %q. Wanted %q", 
                     testcase.instruction, goterr, wanterr)
          }
          // check result type
          if want := testcase.want; got != want {
            t.Errorf("For instruction %q, got %q, want %q.", 
                     testcase.instruction, got, want)
          }
        }
      }
      

      是否符合习惯由社区决定。

      【讨论】:

        猜你喜欢
        • 2021-03-09
        • 1970-01-01
        • 2017-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-07
        • 1970-01-01
        相关资源
        最近更新 更多