はじめに
開発でgoのテストを書いているときに
errorチェックのテストの書き方の使い分けについて話が出たのでひとつの考え方として残しておく。
また、errorのパッケージとしてgolang.org/x/xerrors
を使用している。
概要
単純にエラーの種類を判断するだけでいいのであれば、xerrors.Is()
の結果をassert.True()
に渡してチェックする。
Is()はbaseとなるerrorが両者で一致していればtrueになるので厳密なチェックにはならない。
具体的なエラーの内容までを見るのであれば、エラー文字列まで見ないといけないので
assert.EqualError()
を使用する。
テスト対象のコード
package main
import (
"golang.org/x/xerrors"
)
var baseDBErr = xerrors.New("db error")
var baseCacheErr = xerrors.New("cache error")
func main() {
handler()
}
// テスト対象のfunc
func handler() error {
if false {
return err1()
}
if false {
return err2()
}
if true {
return err3()
}
return nil
}
// DB系のエラー
func err1() error {
return xerrors.Errorf("t_user取得失敗: %w", baseDBErr)
}
// キャッシュ系のエラー
func err2() error {
return xerrors.Errorf("マスターA取得失敗: %w", baseCacheErr)
}
// キャッシュ系のエラー
func err3() error {
return xerrors.Errorf("マスターB取得失敗: %w", baseCacheErr)
}
テストコード
package main
import (
"testing"
"github.com/stretchr/testify/assert"
"golang.org/x/xerrors"
)
func TestHandler(t *testing.T) {
fail := map[string]struct {
wantErr error
wantStrErr string
}{
"テストケースA": {
wantErr: baseCacheErr,
wantStrErr: "マスターB取得失敗: cache error",
},
}
t.Run("失敗", func(t *testing.T) {
for tt, tc := range fail {
t.Run(tt, func(t *testing.T) {
err := handler()
// キャッシュエラーかどうかは判断できるが、マスターAかBどちらの処理のエラーなのかがわからない
assert.True(t, xerrors.Is(err, tc.wantErr))
// 厳密なチェック(文字列をチェック)
assert.EqualError(t, err, tc.wantStrErr)
})
}
})
}