Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error type checking in Go for unit table tests

I want to test the type of the error returned against a table test of expected results, like so:

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

In the example above, different error sub-classes are returned based on the type of error that occurred. You may imagine that the caller of the made-up Thesaurus function would handle each error type differently.

What is the idiomatic way to assert that the type of error returned, and the type of error expected, are the same?

like image 919
Alex Avatar asked Apr 29 '14 19:04

Alex


2 Answers

Use a type switch.

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

It's definitely not as succinct as the reflect way of doing it, but I think it's more Go-ish and explicit.

like image 159
Linear Avatar answered Oct 03 '22 18:10

Linear


There's also this idiom:

In Thesaurus...

import "errors"

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

In Testcase...

if err != testcase.err {

}

However, I think in this idiom the errors must be defined in advance (i.e. the message cannot be changed).

like image 28
Alex Avatar answered Oct 03 '22 20:10

Alex