4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

testifyパッケージのassert/requireとは? [Go]

Last updated at Posted at 2024-10-28

Goのテストケースを実装した際に、testifyパッケージのrequireとasserを使ったのですが、あまり違いがわからなかったことありませんか?

今回は、Goのテストコードでよく使われるtestify/assertパッケージとtestify/requireパッケージの違いと、それぞれのメソッドについて調べてみようと思います。

assertとrequireはどのような役割をしているのか

この二つは、testifyパッケージに入っているテスト用ツールです。

違いは以下のようになっています。

パッケージ名 違い
assert テストが失敗しても実行し続ける
require テストが失敗したら即時終了

主な違いはテストが失敗しても実行し続けるか終了するかの違いになっています。

インストール

下のコマンドで、go.modに依存関係を追加してください。

zsh
go get github.com/stretchr/testify

assertとrequireの使い方

assertとrequireは基本的の同じメソッドを持っていて、主なメソッド名と機能は下のようになっています。

値と型の比較

メソッド 機能
Equal 値を比較
EqualValues 型関係なしに値が同じか比較
Exactly 型があっているかどうかまで厳密に比較
IsType 同じ型か比較

Equal

Equal()では、値の確認が行えます。

go
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
go
assert.Equal(t, 123, 123) //-> Success
assert.Equal(t, 123, 321) //-> Fail

EqualValues

EqualValues()では、型関係なしに値が同じか確認できます。

例えば下のようにuint32とint32のように、整数ではあるけれども実際には型が異なっていても、値が同じか確認することができます。

go
assert.EqualValues(t, uint32(123), int32(123)) //-> Success

Exactly

Equal()の厳密版のようなメソッドで、型があっているかどうかまで厳密に比較してくれます。

func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool
go
assert.Exactly(t, int32(123), int64(123))//-> Success

IsType

型が同じかどうか比較してくれます。

go
type A struct{
    a sting
}

type B struct{
    b stirng
}
a := A("1")
b := B("1")
a2 := A("2")

assert.IsType(t, a, a2) //-> Success

assert.IsType(t, a, b)  //-> Fail

リストと要素の比較

メソッド 機能
ElementMatch リストの比較
Len スライスの要素数を検証
Contains 含まれるかどうか検証
NotContains 含まれないことを検証

ElementMatch

listの比較が行えます。
返ってきたlistが思い通りの結果かどうかの確認に使用できます。

go
func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool)
assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) //-> Fail

Len

スライスの要素数を検証できます。

スライスを返すメソッドで、想定されている数の要素数が返ってきているかを確認します。

go
myslice := make([]int,3)

assert.Len(t, mySlice, 3) //-> Success
assert.Len(t, mySlice, 4) //-> Fail

Contains

スライスやmap等で特定のものが含まれているかを確認できます。

go
a.Contains(["Hello", "World"], "World") //-> Success

NotContains

Containsとは逆で、含まれていないかを確認できます。

go
a.NotContains("Hello World", "Earth") //-> Success

JSONの比較

メソッド 機能
JSONEq JSONが同じかどうか比較

JSONeq

JSONが同じかどうか比較できます。

go
assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)

エラーの検証

メソッド 機能
EqualError 返されたエラーが同じかどうか比較
Error エラーが返されるか検証
NoError エラーがないことを検証

EqualError

エラーの内容を比較することができます。

nilでも比較することが可能です。

go
actualObj, err := SomeFunction()
assert.EqualError(t, err,  expectedErrorString)

Error

エラーが同じかどうかを確認できます。

エラーを自作した時とかに使えそうですね。

go
actualObj, err := SomeFunction()
if assert.Error(t, err) {
	assert.Equal(t, expectedError, err)
}

NoError

こちらはエラーがないとき(nil)かどうかを判断できます。

go
actualObj, err := SomeFunction()
  if assert.NoError(t, err) {
	   assert.Equal(t, expectedObj, actualObj)
  }

その他の検証

メソッド 機能
Empty 値が空か検証
False falseかどうか検証
NotNil nil(null)でないかを検証

Empty

値が空かを検証できます。
空と判定されるのは,nil,0,"",falseです。

go
a.Empty(obj)

False

値がFalseかどうかを検証できます。

Emptyではなく、Falseかどうかを確認したいという目的の時はこちらの方が良さそうです。

go
assert.False(t, myBool)

NotNil

nilではないかを検証できます。

Emptyと似ていますが、コンテキストによってはこちらを採用する方が良いかもしれません。

go
assert.NotNil(t, err)

assertを使ってみる

assertを使ってみようと思います。

実際に下のように実装してみました。

go
task := entity.Todo{
	Task:     "test",
	Deadline: time,
}

mrTodo.EXPECT().Insert(gomock.Any(), gomock.Any()).Return(&entity.Todo{Task: "test", Done: false, Deadline: time}, nil)

taskRes, err := usc.Create(ctx, &task)

assert.NoError(t, err)
assert.NotNil(t, taskRes)
assert.Equal(t, "test", taskRes.Task)
assert.False(t, false, taskRes.Done)
assert.Equal(t, time, taskRes.Deadline)

実際にテストをしてみました。

成功した場合は下のように表示されます。

zsh
❯  go test -v ./...
=== RUN   TestCreate
2024/10/16 19:26:45 deadline 2024-10-11 00:00:00 +0000 UTC
--- PASS: TestCreate (0.00s)
PASS
ok      github.com/maooz4426/Todolist/usecases/interactor       0.251s

失敗した場合を確認するためにしたようなコードを追加してみました。

go
assert.NoError(t, err)
assert.NotNil(t, taskRes)
assert.Equal(t, "a", taskRes.Task)
log.Println("failしたよ〜ん") //追加
assert.False(t, false, taskRes.Done)
assert.Equal(t, time, taskRes.Deadline)

実際にテストを実行すると下のようになります。

zsh
❯  go test -v ./...
=== RUN   TestCreate
    todo_test.go:39:
                Error Trace:    /Users/maoz/Documents/Go/todo-go-clean/usecases/interactor/todo_test.go:39
                Error:          Not equal:
                                expected: "a"
                                actual  : "test"

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1 +1 @@
                                -a
                                +test
                Test:           TestCreate
2024/10/16 19:34:27 failしたよ〜ん
--- FAIL: TestCreate (0.00s)
FAIL

失敗しても実行が継続されています。

requireを使ってみる

requireは上のコードを使って、パッケージだけ変えて使ってみようと思います。

go
require.NoError(t, err)
require.NotNil(t, taskRes)
require.Equal(t, "a", taskRes.Task)
log.Println("failしたよ〜ん")
require.False(t, false, taskRes.Done)
require.Equal(t, time, taskRes.Deadline)

requireではassertと違い、テストを失敗すると、そこで実行が終了します。

zsh
❯  go test -v ./...
=== RUN   TestCreate
    todo_test.go:39:
                Error Trace:    /Users/maoz/Documents/Go/todo-go-clean/usecases/interactor/todo_test.go:39
                Error:          Not equal:
                                expected: "a"
                                actual  : "test"

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1 +1 @@
                                -a
                                +test
                Test:           TestCreate
--- FAIL: TestCreate (0.00s)

まとめ

tesitifyパッケージを使うと楽にテストを書くことができるのに加え、多くのメソッドがあるためコードを読みやすく書くこともできると感じました。

ぜひテストケースを書くときは使ってみつつ、やりたいことを抽象化したメソッドがないか調べてみてください

Go関連の記事

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?