🧪
【Go】Goのテストに入門してみた! ~go-cmp編~
はじめに
前回は「Testify」を見ていきました。
今回は「go-cmp」に入門します!
前回の記事はこちら!
この記事でわかること
-
go-cmp
の概要 -
go-cmp
を使った構造体比較の基本 -
go-cmp
を使った複合体を含む構造体比較の方法
go-cmpとは?
go-cmp
は、Googleが提供しているGo用の比較ライブラリです。
標準の reflect.DeepEqual()
よりも柔軟で細かい制御が必要なケースで活躍します。
特徴としては以下のような点があります。
- 複雑な構造体やネストされたデータでも比較できる
- フィールド単位で無視(Ignore)や変換(Transformer)を指定できる
- 比較結果を見やすい差分(diff)として表示できる
比較結果が差分として出力されるため、どこが違うのか一目で確認できます。
go-cmpを使った構造体比較の基本
基底型のみで構成されている構造体を、go-cmp
を使って比較してみます。
main_test.go
package main
import (
"testing"
"github.com/google/go-cmp/cmp"
)
type User struct {
ID int
Name string
Age int
}
func TestStruct(t *testing.T) {
u1 := User{ID: 1, Name: "Taro", Age: 20}
u2 := User{ID: 1, Name: "Taro", Age: 20}
if diff := cmp.Diff(u1, u2); diff != "" {
t.Errorf("u1 and u2 are not equal")
}
}
実行すると、以下のような結果を得ることができます。
ターミナル
# go test -v
=== RUN TestStruct
--- PASS: TestStruct (0.00s)
PASS
ok go-test-practice 0.320s
Diff()のシグネチャ
Diff()
のシグネチャは以下の通りです。
compare.go
func Diff(x, y interface{}, opts ...Option) string
-
x, y interface{}
- 比較対象の2つの値を渡す
- 型は任意で、空インターフェースなのでどんな型でも受け取れる
-
opts ...Option
- 可変長引数で、比較の仕方をカスタマイズできる
- 戻り値 string
- 比較結果の差分を文字列として返す
- 空文字列なら一致を意味し、差分がある場合は「-(左側の値), +(右側の値)」の形式で表示
戻り値がユニークなのが特徴です。
テストに失敗すると、以下のような結果を得ることができます。
ターミナル
# go test -v
=== RUN TestStruct
main.User{
- ID: 2,
+ ID: 1,
Name: "Taro",
Age: 20,
}
main_test.go:21: u1 and u2 are not equal
--- FAIL: TestStruct (0.00s)
FAIL
exit status 1
FAIL go-test-practice 0.234s
複合型を含む構造体比較
一方で、複合型を含む構造体を比較する場合は、以下のように実装しテストすることができます。
main_test.go
package main
import (
"testing"
"github.com/google/go-cmp/cmp"
)
type User struct {
ID int
Name string
Age int
Hobby []string
}
func TestStruct(t *testing.T) {
u1 := User{ID: 1, Name: "Taro", Age: 20, Hobby: []string{"reading", "running"}}
u2 := User{ID: 1, Name: "Taro", Age: 20, Hobby: []string{"reading", "running"}}
if diff := cmp.Diff(u1, u2); diff != "" {
t.Errorf("u1 and u2 are not equal")
}
}
実行すると、以下のような結果を得ることができます。
ターミナル
# go test -v
=== RUN TestStruct
--- PASS: TestStruct (0.00s)
PASS
ok go-test-practice 0.193s
テストに失敗すると、以下のような結果を得ることができます。
ターミナル
# go test -v
=== RUN TestStruct
main.User{
ID: 1,
Name: "Taro",
Age: 20,
Hobby: []string{
"reading",
- "running",
+ "walking",
},
}
main_test.go:22: u1 and u2 are not equal
--- FAIL: TestStruct (0.00s)
FAIL
exit status 1
FAIL go-test-practice 0.297s
まとめ
今回は「go-cmp」について学びました。
go-cmp
は、Goで値や構造体を比較するときに非常に便利なライブラリです。
reflect.DeepEqual()
でも比較はできますが、差分が見やすく表示される点や、比較ルールを柔軟にカスタマイズできる点で go-cmp
が優れています。
特に、APIレスポンスやDBからの取得結果など、複雑なデータ構造をテストする場面で力を発揮します。
シンプルさと柔軟さを兼ね備えた go-cmp
は、Goのテストにおける強力な選択肢のひとつです。
今回で、「Goのテストに入門してみた!」シリーズをおしまいにします!
全19回でテストの基本やさまざまなテクニックを知ることができました!
Discussion