投稿日
November 3, 2024
最終更新
November 3, 2024
カテゴリー
tech
タグ
#Go
Goで記述するテストの基礎的な仕組みについてまとめる。
利用するパッケージ
testing
- Go標準のテストパッケージ
- testing package - testing - Go Packages
https://github.com/stretchr/testify/assert
- アサーション用パッケージ
- assert package - github.com/stretchr/testify/assert - Go Packages
- Goは標準ではアサートの仕組みがないが、PHPUnitなどと同じような書き方をしたかったので今回は利用する。
- アサートがない思想については、Go の Test に対する考え方などが参考にできそう。
テスト対象のコード
テスト対象は、シンプルに足し算を行うコードをサンプルとして利用する。
package calc
func Sum(a, b int) int {
return a + b
}
テストの記述
Goのテストファイルは、テスト対象のファイル名の末尾に_test
を追加したものにする。
calc.go
であれば、テストファイルはcalc_test.go
にする。
テスト関数名は、TestXXX
にし、*testing.T
型の引数をとる。
package calc
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSum(t *testing.T) {
actual := Sum(1, 2)
expected := 3
assert.Equal(t, expected, actual)
}
テストの実行
go test
コマンドでテストを実行する。-run
オプションを利用することで、特定のメソッドを指定できる。
go test -run TestSum
その他のテスト実行方法は別途まとめる。
実行結果。
PASS
ok calc 0.003s
-v
オプションを付けることで、テストの詳細を出力できる。
=== RUN TestSum
--- PASS: TestSum (0.00s)
PASS
ok calc 0.003s
t.Runを利用したサブテスト
t.Run
メソッドを利用して、サブテストを作成できる。
func (t *T) Run(name string, f func(t *T)) bool
記述するものは、名前とテストコードの関数。
func TestSum2(t *testing.T) {
t.Run("正の数値", func(t *testing.T) {
actual := Sum(1, 2)
expected := 3
assert.Equal(t, expected, actual)
})
t.Run("負の数値", func(t *testing.T) {
actual := Sum(-1, -2)
expected := -3
assert.Equal(t, expected, actual)
})
}
go test -v -run TestSum2
で実行。
=== RUN TestSum2
=== RUN TestSum2/正の数値
=== RUN TestSum2/負の数値
--- PASS: TestSum2 (0.00s)
--- PASS: TestSum2/正の数値 (0.00s)
--- PASS: TestSum2/負の数値 (0.00s)
PASS
ok calc 0.003s
テストの並列実行
t.Parallel
を利用することで、テストを並列に実行できる。
並列化していない場合は、2秒かかるテストを用意した。
// 並列化していない場合
func TestSum3(t *testing.T) {
t.Run("正の数値", func(t *testing.T) {
actual := Sum(1, 2)
expected := 3
time.Sleep(1 * time.Second)
assert.Equal(t, expected, actual)
})
t.Run("負の数値", func(t *testing.T) {
actual := Sum(-1, -2)
expected := -3
time.Sleep(1 * time.Second)
assert.Equal(t, expected, actual)
})
}
go test -v -run TestSum3
で実行する。
=== RUN TestSum3
=== RUN TestSum3/正の数値
=== RUN TestSum3/負の数値
--- PASS: TestSum3 (2.00s)
--- PASS: TestSum3/正の数値 (1.00s)
--- PASS: TestSum3/負の数値 (1.00s)
PASS
ok calc 2.005s
calc のテストに2秒ほどかかっている。
このテストにt.Parallel
を追加してみる。
// 並列化してテストを実行
func TestSum4(t *testing.T) {
t.Run("正の数値", func(t *testing.T) {
t.Parallel()
actual := Sum(1, 2)
expected := 3
time.Sleep(1 * time.Second)
assert.Equal(t, expected, actual)
})
t.Run("負の数値", func(t *testing.T) {
t.Parallel()
actual := Sum(-1, -2)
expected := -3
time.Sleep(1 * time.Second)
assert.Equal(t, expected, actual)
})
}
go test -v -run TestSum4
で実行する。
=== RUN TestSum4
=== RUN TestSum4/正の数値
=== PAUSE TestSum4/正の数値
=== RUN TestSum4/負の数値
=== PAUSE TestSum4/負の数値
=== CONT TestSum4/正の数値
=== CONT TestSum4/負の数値
--- PASS: TestSum4 (0.00s)
--- PASS: TestSum4/負の数値 (1.00s)
--- PASS: TestSum4/正の数値 (1.00s)
PASS
ok calc 1.003s
calc のテストが約1秒で完了するようになる。
失敗するテスト
テストに失敗した場合の挙動についても確認する。
失敗するテストを用意した。
func TestSum5(t *testing.T) {
actual := Sum(1, 2)
expected := 4 // 本来は3である
assert.Equal(t, expected, actual)
}
go test -v -run TestSum5
で実行する。
=== RUN TestSum5
calc_test.go:78:
Error Trace: /home/runner/workspace/calc_test.go:78
Error: Not equal:
expected: 4
actual : 3
Test: TestSum5
--- FAIL: TestSum5 (0.00s)
FAIL
exit status 1
FAIL calc 0.003s
TestSum5
が失敗していることと、実際のexpected
の値とactual
の値について確認できる。
作成したコード
アサーションの種類
github.com/stretchr/testify
では複数種類のアサーションが用意されている。
// 2つのオブジェクトが等価であること
assert.Equal(t, 3, 3)
// 2つのオブジェクトが等価ではないこと
assert.NotEqual(t, 3, 4)
// オブジェクトがゼロ値、もしくは長さが0のスライスであること
assert.Empty(t, 0)
assert.Empty(t, "")
assert.Empty(t, []int{})
// エラーであること
err := errors.New("error")
assert.Error(t, err)
// エラーではないこと(nilであること)
err = nil
assert.NoError(t, err)
// 1番目の要素が、2番目の要素以上であること
assert.GreaterOrEqual(t, 2, 1)
// オブジェクトが特定の長さを持っていること
assert.Len(t, []int{1, 2}, 2)
// nilであること
err = nil
assert.Nil(t, err)
// nilではないこと
v := 0
assert.NotNil(t, v)
// ゼロ値であること
v = 0
assert.Zero(t, v)
詳しくは、assertを参照。