概要
初めての Go 言語の テスト の章が勉強になったのでそのまとめです。
まとめ
- テストは製品版と同じディレクトリ、パッケージに置く
エクスポートされていない関数や変数にもアクセスしてテストが可能 - ファイル名は xxx_test.go とする
- テスト関数は Test という prefix を付けて *testing.T 型の引数を1つだけ取り、名前は t にするのが慣習
関数のユニットテストは TestMethod と Test のあとに関数名にする
エクスポートされていない関数の場合 Test_method と _ を間に入れる
package sample import "testing" func Test_privateFunc(t *testing.T) { res := privateFunc() if res != "sample" { t.Error("failed", res) } }
- 検証結果が正しくなければ t.Error を使う
t.Fatal を使うとテスト関数を終了させられる - go test ./... でカレント、サブディレクトリ全て実行
-v で詳細な出力
$ go test -v === RUN Test_privateFunc --- PASS: Test_privateFunc (0.00s) PASS ok testing-go/sample 0.110s
- TestMain という関数を使えば before, after のようなことが実現できる
ただしテストごとに呼ばれない
package sample_test import ( "fmt" "testing" "testing-go/sample" "github.com/google/go-cmp/cmp" ) func TestMain(m *testing.M) { fmt.Println("before") m.Run() fmt.Println("after") } func TestPublicFunc(t *testing.T) { expected := sample.Sample{ FirstName: "first", LastName: "last", } res := sample.PublicFunc() if diff := cmp.Diff(expected, res); diff != "" { t.Error(res) } }
go test -v sample2_test.go before === RUN TestPublicFunc --- PASS: TestPublicFunc (0.00s) === RUN TestPublicFunc2 --- PASS: TestPublicFunc2 (0.00s) PASS after ok command-line-arguments 0.120s
- 公開されている API はパッケージを import することでテスト可能
- テスト結果は go-cmp というパッケージを利用することで簡単にできる
GitHub - google/go-cmp: Package for comparing Go values in tests
package sample import ( "testing" "github.com/google/go-cmp/cmp" ) func Test_privateFunc(t *testing.T) { expected := Sample{ Name: "name", } res := privateFunc() if diff := cmp.Diff(expected, res); diff != "" { t.Error(res) } }
- 比較したくないフィールドがある場合はローカル関数として比較関数を定義する
package sample import ( "testing" "github.com/google/go-cmp/cmp" ) func Test_privateFunc(t *testing.T) { expected := Sample{ FirstName: "first", LastName: "first", } comparer := cmp.Comparer(func(x, y Sample) bool { return x.FirstName == y.FirstName }) res := privateFunc() if diff := cmp.Diff(expected, res, comparer); diff != "" { t.Error(res) } }
- 無名構造体を定義してテーブルテストを行う
- -cover オプションでコードカバレッジの出力
-coverprofile=c.out でファイルへの保存
go tool cover -html=c.out で HTML を生成
$ go test -cover PASS coverage: 100.0% of statements ok testing-go/sample 0.228s
- BenchmarkMethod で始まる関数はベンチマーク
testing.B 型の引数を取る
testing.T + ベンチマークの機能が備わっている - go test -bench で実行可能
実行したいベンチマークの名前を正規表現で指定する
. ですべてのベンチマークを実行
-benchmem でメモリ割り当て情報を含める
var blackhole sample.Sample func BenchmarkPublicFunc(b *testing.B) { res := sample.PublicFunc() blackhole = res }
go test ./sample2_test.go -bench=. -benchmem before goos: darwin goarch: arm64 BenchmarkPublicFunc-8 1000000000 0.0000002 ns/op 0 B/op 0 allocs/op PASS after ok command-line-arguments 0.323s
- httptest を使えば http request が行われる関数のテストが容易に可能
- httptest.NewServer は未使用なポートをランダムに使用して HTTP サーバーを serve してくれる
- go test -short で時間のかかるテストをスキップできる
- -race ではレースチェッカーを有効にできる
Go での開発経験がなくテスト周りの基礎から学びたかったので内容がちょうど良かったです。
モック、スタブなどもう少し実践的なテクニックの理解が必要な気がしているので他の書籍も合わせて学びたいと思います。