🧪

【Go】Goのテストに入門してみた! ~Testify編~

に公開

はじめに

前回は「構造体の比較テスト」を見ていきました。
今回は「Testify」に入門します!

前回の記事はこちら!

この記事でわかること

  • stretchr/testify の概要
  • stretchr/testify を使った構造体比較の基本
  • stretchr/testify を使った複合型構造体比較の方法

Testifyとは?

stretchr/testify は、Goでテストを書くときによく使われる、アサーションライブラリ兼モックライブラリ です。
標準の testing パッケージを補完し、テストコードを短く・読みやすく・書きやすくしてくれます。

Testifyを使った構造体比較の基本

基底型のみで構成されている構造体の比較は、以下のように実装しテストすることができました。

main_test.go
package main

import (
    "reflect"
    "testing"
)

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 reflect.DeepEqual(u1, u2) {
        t.Errorf("u1 and u2 are not equal")
    }
}

このテストコードを、Testify を使うことで、より簡単に比較することができます。

main_test.go
package main

import (
    "testing"
    
    "github.com/stretchr/testify/assert"
)

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}
    assert.Equal(t, u1, u2, "they should be equal")
}

実行すると、以下のような結果を得ることができます。

ターミナル
# go test -v
=== RUN   TestStruct
--- PASS: TestStruct (0.00s)
PASS
ok      go-test-practice        0.306s

Equal() のシグネチャは以下の通りです。

assertions.go
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
// 第一引数:テストのコンテキストを表し、通常は*testing.Tを渡す
// 第二引数:期待値
// 第三引数:実際に得られた値
// 第四引数:任意のエラーメッセージや追加情報を指定できる(省略可能)
// 返り値:比較結果

複合型を含む構造体比較

一方で、複合型を含む構造体を比較する場合は、以下のように実装しテストすることができます。

main_test.go
package main

import (
    "reflect"
    "testing"
)

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 !reflect.DeepEqual(u1, u2) {
        t.Errorf("u1 and u2 are not equal")
    }
}

このテストコードを、Testify を使うことで、より簡単に比較することができます。

main_test.go
package main

import (
    "testing"
    
    "github.com/stretchr/testify/assert"
)

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"}}
    assert.Equal(t, u1, u2, "u1 and u2 are not equal")
}

実行すると、以下のような結果を得ることができます。

ターミナル
# go test -v
=== RUN   TestStruct
--- PASS: TestStruct (0.00s)
PASS
ok      go-test-practice        0.347s

まとめ

今回は「Testify」について学びました。

標準ライブラリだけでも構造体の比較テストは可能ですが、reflect.DeepEqual を使うと記述がやや冗長になりがちです。

一方で、stretchr/testifyassert.Equal を使えば、

  • 基底型だけの構造体
  • スライスやマップを含む複合型の構造体

これらを同じ書き方でシンプルに比較できます。
さらに、エラーメッセージを簡単に付けられるため、失敗時の原因追跡もしやすくなります。
テストコードを短く・読みやすく・保守しやすくしたい場合は、stretchr/testify を導入するメリットは大きいといえるでしょう。

次回は「go-cmp」に入門します!

参考

Discussion