LoginSignup
3
3

More than 1 year has passed since last update.

Golang単体テストでstruct中身をassertするファクション

Last updated at Posted at 2021-05-17

単体テストを書いていますが、どうやって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の全てのフィールドを回して、expectactualを比較する。
  • time.Timeの型はUnix()でsecondに変換して比較する
  • 呼び出す側はこんな感じ: AssertStruct(t, reflect.ValueOf(&expect).Elem(), reflect.ValueOf(&actual).Elem())
3
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3