Go for unit table tests中的错误类型检查

时间:2014-04-29 19:30:46

标签: unit-testing testing error-handling go

我想测试针对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
  }
}

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

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

3 个答案:

答案 0 :(得分:2)

使用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和显性。

答案 1 :(得分:1)

还有这个成语:

在词库中......

import "errors"

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

在Testcase中......

if err != testcase.err {

}

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

答案 2 :(得分:0)

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)
    }
  }
}

它是否适合社区决定。