go-cmpを使ってテスト結果と期待値を比較することができますが、さらにOptionを使うことで色々な比較をすることができるようになります。よく業務でテストを書く時に使うOptionのTipsを紹介していきます。
IgnoreFieldsを使って、特定の項目を比較しない
IgnoreFieldsを使うことで、特定の項目は比較をしないようにすることができます。利用例として、プログラム側で生成するようなIDや作成日、更新日などテストで期待値が固定値にしにくいものはIgnoreFieldsを使って比較されないようにします。
package test
import (
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)
type User struct {
ID int64
Name string
CreatedAt time.Time
}
func TestUser(t *testing.T) {
now := time.Now()
user1 := User{
ID: 20,
Name: "太郎",
CreatedAt: now,
}
user2 := User{
ID: 20,
Name: "太郎",
CreatedAt: now.Add(time.Hour),
}
opts := cmp.Options{
// 比較をしないフィールドを設定
cmpopts.IgnoreFields(User{}, "CreatedAt"),
}
// cmp.Diffの引数にopts...をつけることで、optsで設定したオプションで、比較をする
if diff := cmp.Diff(user1, user2, opts...); diff != "" {
t.Errorf("結果で差分が出てます\n %s", diff)
}
}
実行結果の比較
IgnoreFieldsをオプションに追加しなかった場合
CreatedAtで差分が発生
% go test
--- FAIL: TestUser (0.00s)
ignore_test.go:36: 結果で差分が出てます
test.User{
ID: 20,
Name: "太郎",
- CreatedAt: s"2024-05-14 19:27:01.020786 +0900 JST m=+0.001027711",
+ CreatedAt: s"2024-05-14 20:27:01.020786 +0900 JST m=+3600.001027711",
}
FAIL
exit status 1
FAIL test/blog/go-cmp/ignore 0.231s
IgnoreFieldsをオプションに追加した場合
エラーなく成功する
% go test
PASS
ok test/blog/go-cmp/ignore 0.319s
SortSlicesで構造体を比較する
SortSlicesを使うことで、2つのスライス同士をソートして比較ができます。
使用例として、構造体のスライス同士を比較する時に、テストの結果と期待値で中身の順番が違うことがありテストが失敗をしてしまうことがあります。その時にfmt.Sprintf(“%v”, {構造体変数})で構造体を文字列に変えてあげて、SortSlicesを使うことで2つの構造体のスライスが比較できます。
package sort
import (
"fmt"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)
type User struct {
ID int64
Name string
CreatedAt time.Time
}
type Users []User
func TestUsers(t *testing.T) {
now := time.Now()
users1 := Users{
{
ID: 20,
Name: "太郎",
CreatedAt: now,
},
{
ID: 30,
Name: "士郎",
CreatedAt: now,
},
}
users2 := Users{
{
ID: 30,
Name: "士郎",
CreatedAt: now,
},
{
ID: 20,
Name: "太郎",
CreatedAt: now,
},
}
opts := cmp.Options{
cmpopts.SortSlices(func(i, j interface{}) bool {
// interface型を文字に変換にして、比較できるようにする
return fmt.Sprintf("%v", i) < fmt.Sprintf("%v", j)
}),
}
if diff := cmp.Diff(users1, users2, opts...); diff != "" {
t.Errorf("結果で差分が出てます\n %s", diff)
}
}
実行結果の比較
SortSlicesをオプションに追加しなかった場合
順番が違うのでID、Nameで差分が発生している。
% go test
--- FAIL: TestUsers (0.00s)
sort_test.go:56: 結果で差分が出てます
sort.Users{
{
- ID: 20,
+ ID: 30,
- Name: "太郎",
+ Name: "士郎",
CreatedAt: s"2024-05-14 19:28:30.424131 +0900 JST m=+0.001001234",
},
{
- ID: 30,
+ ID: 20,
- Name: "士郎",
+ Name: "太郎",
CreatedAt: s"2024-05-14 19:28:30.424131 +0900 JST m=+0.001001234",
},
}
FAIL
exit status 1
FAIL test/blog/go-cmp/sort 0.267s
SortSlicesをオプションに追加した場合
エラーなく成功する
% go test
PASS
ok test/blog/go-cmp/sort 0.289s
まとめ
今回はgo-cmpのOptionを使って、簡単にテスト結果と期待値を比較する方法について解説をしてきました。
他にもテストやGo言語について以下のような記事を書いてますので、興味あれば読んでもらえたらと思います。
- テストコードを書く時にあるテストでDBを更新して、その更新が他のテストに影響を与えてエラーが発生してしまう問題の対策
- Go言語でMockを使ってテストする方法
- gorutineの同時実行数を効率的に制御する方法
- Goで空の構造体を使ってメモリ効率の良いコードを実装する方法
【おすすめ記事のリンク】
コメント