Help us understand the problem. What is going on with this article?

構造体などをテストするのに便利なgoogle/go-cmpの使い方

More than 1 year has passed since last update.

Goでテストを書きたいときにjsonや大きめの構造体で返ってくる戻り値をテストしたいニーズがありますよね。
そのようなニーズに対して、golang.tokyo#17にて発表されたTips for develoepr-friendly testingのスライドでご紹介いただいた、google/go-cmpを実際に使ってとても便利だったので、ここに使い方を残しておきます。

google/go-cmp

google/go-cmpはGoogle非公式の値比較のライブラリです。

This package is intended to be a more powerful and safer alternative to reflect.DeepEqual for comparing whether two values are semantically equal.

使い方

インストール

go get -u github.com/google/go-cmp/cmp

depなどをお使いの方は別途それぞれの方法で。

Diff

使い方の参考としては、https://godoc.org/github.com/google/go-cmp/cmp#example-Diff--Testing に記載のあるexampleコードがベースです。

例えば、下記のようなメソッドがあった場合を仮定します。

main.go
type Hoge struct {
    Moji string
    AnotherStruct Huga
    Num int
    Flag bool
}

type Huga struct {
    Moji string
}

// Hogeを返す
func FuncHoge() Hoge {
    h := Hoge{
        Moji: "hogehoge",
        AnotherStruct: Huga{
            Moji: "hugahuga",
        },
        Num: 1,
        Flag: false,
    }
    return h
}

上記のメソッドを返り値をチェックする場合は次のように使用します。

main_test.go
func TestFuncHoge(t *testing.T) {
    expected := Hoge{
        Moji: "hogehoge",
        AnotherStruct: Huga{
            Moji: "hugahuga",
        },
        Num: 1,
        Flag: false,
    }
    res := FuncHoge()
    if diff := cmp.Diff(res, expected); diff != "" {
        t.Errorf("Hogefunc differs: (-got +want)\n%s", diff)
    }
}

テストコード内の、cmp.Diff()google/go-cmpが提供している機能です。

https://github.com/google/go-cmp/blob/master/cmp/compare.go#L98

func Diff(x, y interface{}, opts ...Option) string

戻り値がstring型で、diffがない場合は空文字列で返ってくるので、次のように書いていきます。

if diff := cmp.Diff(res, expected); diff != "" {
    t.Errorf("Hogefunc differs: (-got +want)\n%s", diff)
}

実際に差分があった場合は次のようなテスト結果が表示されます。

=== RUN   TestFuncHoge
--- FAIL: TestFuncHoge (0.00s)
    main.go:56: Hogefunc differs: (-got +want)
        {Hoge}.AnotherStruct.Moji:
            -: "hugahuga"
            +: "hugahuga_diff"
FAIL

とても見やすいですね。

その他

オプションも付けれるので詳しく設定されたい方は次のExampleを参照してみてください。

https://godoc.org/github.com/google/go-cmp/cmp#pkg-examples

binc
Eコマースプラットフォーム「BASE」、オンライン決済サービス「PAY.JP」、購入者向けID型決済サービス「PAY ID」の3つのサービスを運営しています。
https://binc.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away