Go のプロジェクトでちょっと凝ったテスティングをする必要が生じたので、いろいろ調べ物をしたのでそのメモを残しておきたい。
Go test のタイムアウトは?
こちらのページで、go test
のフラグを確認することが出来る。丁寧にかいているのでわかりやすい。-timeout d
で設定できるようだ。
The default is 10 minutes (10m)
Go test で、t.Logf
を書いているのにログが出ない。
フラグの設定が必要。-test.v
をつける。-v
は元々 Verbose output
の意味で、テストの場合は、-test
のプレフィックスをつけるのが必須。
パラメータ付きのテストをしたい
沢山の言語をサポートしている環境で、下記のようなことを実践したい。
- 各言語のテストは、パラレルで実行できない。シリアルでやりたい。
- 各エクステンションのテストは、パラレルで実行したい。
- 通常は全部のテストをランするが、テストの実行をエクステンション及び言語でフィルターしたい
上記のことを実現するために下記のことを調査した。
シリアル・パラレルの切り替え
下記を書くことで、パラレル実行される。なければパラレル実行されない。
t.Parallel()
パラメータによる言語のフィルター
t.Run
を使うと、フィルターをすることができる。
次のプログラムで、t.Run
を使う。t.Run
を設定すると、go routine でそれぞれの関数が実行される。そうすると、並行性が気になるところだが、t.Parallel()
を書かない限り、並行では処理されない。つまり、このプログラムでは、言語ごとに、シリアルで、実行される。
package main
import (
"fmt"
"testing"
"time"
)
func TestKafkaTrigger(t *testing.T) {
t.Parallel()
t.Log("******* kafka testing")
testCase := []string{
"dotnet",
"java",
}
for _, tc := range testCase {
t.Run(fmt.Sprintf("Image=%s", tc), func(t *testing.T) {
// t.Parallel()
t.Logf("Test run not in parallel %s", tc)
time.Sleep(3 * time.Second)
t.Logf("Finish wating for bye 3 sec: %s", tc)
})
}
}
テストの実行時に何も指定しなければ、他のテストケース含めて全部実行される。
$ go test -test.v
=== RUN TestKafkaTrigger
=== PAUSE TestKafkaTrigger
=== RUN TestRabbitMQTriggerTest
=== PAUSE TestRabbitMQTriggerTest
=== CONT TestKafkaTrigger
=== CONT TestRabbitMQTriggerTest
rabbitmq_test.go:7: ******* rabbitmq testing
--- PASS: TestRabbitMQTriggerTest (0.00s)
=== CONT TestKafkaTrigger
kafka_test.go:11: ******* kafka testing
=== RUN TestKafkaTrigger/Image=dotnet
kafka_test.go:20: Test run not in parallel dotnet
kafka_test.go:22: Finish wating for bye 3 sec: dotnet
=== RUN TestKafkaTrigger/Image=java
kafka_test.go:20: Test run not in parallel java
kafka_test.go:22: Finish wating for bye 3 sec: java
--- PASS: TestKafkaTrigger (6.00s)
--- PASS: TestKafkaTrigger/Image=dotnet (3.00s)
--- PASS: TestKafkaTrigger/Image=java (3.00s)
PASS
ok simplearchitect.com 6.006s
テストでフィルタする
-run <Test Function regex>
でマッチする。
$ go test -test.v -run TestKafkaTrigger
=== RUN TestKafkaTrigger
=== PAUSE TestKafkaTrigger
=== CONT TestKafkaTrigger
kafka_test.go:11: ******* kafka testing
=== RUN TestKafkaTrigger/Image=dotnet
kafka_test.go:20: Test run not in parallel dotnet
kafka_test.go:22: Finish wating for bye 3 sec: dotnet
=== RUN TestKafkaTrigger/Image=java
kafka_test.go:20: Test run not in parallel java
kafka_test.go:22: Finish wating for bye 3 sec: java
--- PASS: TestKafkaTrigger (6.01s)
--- PASS: TestKafkaTrigger/Image=dotnet (3.00s)
--- PASS: TestKafkaTrigger/Image=java (3.00s)
PASS
ok simplearchitect.com 6.007s
例えばテストに次の関数を追加する。
:
func TestKafkaTriggerWithSomething(t *testing.T) {
t.Parallel()
t.Log("******* kafka testing something")
}
テストを指定すると前方一致でマッチするので、TestKafkaTriggerWithSomething も一緒にマッチする。
$ go test -test.v -run TestKafkaTrigger
=== RUN TestKafkaTrigger
=== PAUSE TestKafkaTrigger
=== RUN TestKafkaTriggerWithSomething
=== PAUSE TestKafkaTriggerWithSomething
=== CONT TestKafkaTrigger
=== CONT TestKafkaTriggerWithSomething
kafka_test.go:30: ******* kafka testing something
=== CONT TestKafkaTrigger
kafka_test.go:11: ******* kafka testing
=== RUN TestKafkaTrigger/Image=dotnet
kafka_test.go:20: Test run not in parallel dotnet
--- PASS: TestKafkaTriggerWithSomething (0.00s)
=== CONT TestKafkaTrigger/Image=dotnet
kafka_test.go:22: Finish wating for bye 3 sec: dotnet
=== RUN TestKafkaTrigger/Image=java
kafka_test.go:20: Test run not in parallel java
kafka_test.go:22: Finish wating for bye 3 sec: java
--- PASS: TestKafkaTrigger (6.00s)
--- PASS: TestKafkaTrigger/Image=dotnet (3.00s)
--- PASS: TestKafkaTrigger/Image=java (3.00s)
PASS
ok simplearchitect.com 6.006s
防ぎたい場合は、$
をつけて終端であることを示せばよい
$ go test -test.v -run TestKafkaTrigger$
=== RUN TestKafkaTrigger
=== PAUSE TestKafkaTrigger
=== CONT TestKafkaTrigger
kafka_test.go:11: ******* kafka testing
=== RUN TestKafkaTrigger/Image=dotnet
kafka_test.go:20: Test run not in parallel dotnet
kafka_test.go:22: Finish wating for bye 3 sec: dotnet
=== RUN TestKafkaTrigger/Image=java
kafka_test.go:20: Test run not in parallel java
kafka_test.go:22: Finish wating for bye 3 sec: java
--- PASS: TestKafkaTrigger (6.00s)
--- PASS: TestKafkaTrigger/Image=dotnet (3.00s)
--- PASS: TestKafkaTrigger/Image=java (3.00s)
PASS
ok simplearchitect.com 6.004s
パラメータをテストする。
dotnet
もしくは、java
の言語のみテストしたい!という場合どうしようか?
その場合は次のようにしよう。きれいにフィルターされる。まさに思っていた挙動が簡単に実現した!
$ go test -test.v -run TestKafkaTrigger$/java
=== RUN TestKafkaTrigger
=== PAUSE TestKafkaTrigger
=== CONT TestKafkaTrigger
kafka_test.go:11: ******* kafka testing
=== RUN TestKafkaTrigger/Image=java
kafka_test.go:20: Test run not in parallel java
kafka_test.go:22: Finish wating for bye 3 sec: java
--- PASS: TestKafkaTrigger (3.00s)
--- PASS: TestKafkaTrigger/Image=java (3.00s)
PASS
ok simplearchitect.com 3.004s
おまけ Struct オブジェクトの比較をテストの中でしたい。
cmp.Diff が便利。cmp.Equal もあるのだが、cmp.Diff の方が、テストが失敗したときにDiffが出るので何が違うのかわかって便利。
assert.Empty(t, cmp.Diff(expectedFirstSuccess, ((*buildContextCollection).Collection)[0], cmpopts.IgnoreFields(expectedFirstSuccess, "Error")))
Go のテストはまだまだ奥深い。時間をとってしっかり学ぶべきやな。常にテスト駆動でコードが書けるようになりたい。