STORES Product Blog

こだわりを持ったお商売を支える「STORES」のテクノロジー部門のメンバーによるブログです。

go-cmp/cmp/cmpopts のオプション活用事例

はじめに

こんにちは、STORESの高田です。

今回は github.com/google/go-cmp/cmp のオプションの中から、実際のテストコードで使用頻度の高いオプションについてご紹介します。

基本的な使い方

cmp パッケージ用の汎用的なオプションは cmpopts package - github.com/google/go-cmp/cmp/cmpopts - Go Packages で提供されています。以下のように cmp.Diff() への引数として使うことができます。

t.Run("...", func(t *testing.T) {
    ...
    opts := cmpopts.IgnoreFields(dbEmployee{}, "CreatedAt", "UpdatedAt")
    if diff := cmp.Diff(want, got, opts); diff != "" {
        t.Errorf("diff (-want +got):\n%s", diff)
    }
}

使用頻度の高いオプション

実際のテストコードを grep して調べたところ、使用頻度の高い順で、上位3つは以下の通りになっていました。

  • cmpopts.IgnoreFields
  • cmpopts.SortSlices
  • cmpopts.EquateApproxTime

cmpopts.IgnoreFields

cmpopts.IgnoreFields は、一部のフィールドを比較対象から除外したい場合に使用します。実際の使用例としては、データベースから取得した created_atupdated_at カラムの値をテスト対象から除外するために使用するケースで使用されることが多く、7割程がこの利用パターンでした。

t.Run("...", func(t *testing.T) {
    ...
    opts := cmpopts.IgnoreFields(dbEmployee{}, "CreatedAt", "UpdatedAt")
    if diff := cmp.Diff(want, got, opts); diff != "" {
        t.Errorf("diff (-want +got):\n%s", diff)
    }
}

cmpopts.SortSlices

cmpopts.SortSlices は、順序を無視してスライスの比較をするために使用します。実際の使用例としては、 UUID で発番された ID が順不同で取得される場合のテストケースで使用されており、2割程がこの利用パターンでした。

また、オプションは複数指定することもでき、 cmpopts.IgnoreFields と併せて使われているケースが多く見受けられました。

以下のコードのように UUID を文字列としてソートし、順不同のパターンでのテストを行なっています。

opts := cmpopts.SortSlices(func(i, j dbOrganizationTree) bool {
  return i.OrganizationID.String() < j.OrganizationID.String()
})

cmpopts.EquateApproxTime

cmpopts.EquateApproxTime は、 func EquateApproxTime(margin time.Duration) cmp.Option として定義されており、指定した time.Duration 以内であれば値を同一視するオプションです。実際の利用例としては、データベースから取得した time.Time の値をテストするために利用されており、1割程がこの利用パターンでした。

以下のように、期限切れを表す値のテストで利用されるケースが多くありました。

opts := cmpopts.EquateApproxTime(1 * time.Second)
if diff := cmp.Diff(i.CreatedAt.Add(24*time.Hour), i.ExpiresAt, opts); diff != "" {
  t.Errorf("diff (-want +got):\n%s", diff)
}

今回はオプションをご紹介しました。以前の記事 Go言語でのテストヘルパー関数の活用 - STORES Product Blog での github.com/google/go-cmp/cmp の活用方法についても、併せて事例として参考にしてもらえればと思います.