単体テストを書いていますが、どうやってstructの全てのフィールドをassertionする方法をいくつか案考えていました。
struct全体を比較するは ==
と reflect.DeepEqual
ができると思いますが
-
==
の場合、structにpointerが入るとfalseになる -
DeepEqual
はtime.Timeの型が入るとnano秒までの同じじゃないとダメらしいです。 -
DeepEqual
の場合はどのフィールドが相違かどうかがわからないです。 -
DeepEqual
はカスタマイズがしにくいです。例えばあるフィールドをassertionがいらないケースもあるかもしれない。
=> ==
と reflect.DeepEqual
があまりイケてないのでcustomファクションを作りました
まず、このpackageを使う
github.com/stretchr/testify
func AssertStruct(t *testing.T, expect, actual reflect.Value) {
typeOfExpect := expect.Type()
for i := 0; i < expect.NumField(); i++ {
expectField := expect.Field(i)
actualField := actual.FieldByName(typeOfExpect.Field(i).Name)
if expectField.Type().String() == "time.Time" {
assert.Equal(t, expectField.Interface().(time.Time).Unix(), actualField.Interface().(time.Time).Unix(), fmt.Sprintf("%s should be equal", typeOfExpect.Field(i).Name))
} else if expectField.Type().String() == "*time.Time" && expectField.Interface().(*time.Time) != nil && actualField.Interface().(*time.Time) != nil {
assert.Equal(t, expectField.Interface().(*time.Time).Unix(), actualField.Interface().(*time.Time).Unix(), fmt.Sprintf("%s should be equal", typeOfExpect.Field(i).Name))
} else {
assert.Equal(t, expectField.Interface(), actualField.Interface(), fmt.Sprintf("%s should be equal", typeOfExpect.Field(i).Name))
}
}
}
- 基本の処理をStructの全てのフィールドを回して、
expect
とactual
を比較する。 - time.Timeの型はUnix()でsecondに変換して比較する
- 呼び出す側はこんな感じ:
AssertStruct(t, reflect.ValueOf(&expect).Elem(), reflect.ValueOf(&actual).Elem())