1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Go の Unit Testing に関してやりたいことを調べてみた - パラメータによるフィルタリングと並行性の制御

Last updated at Posted at 2021-03-22

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() を書かない限り、並行では処理されない。つまり、このプログラムでは、言語ごとに、シリアルで、実行される。

kafka_test.go
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

例えばテストに次の関数を追加する。

kafka_test.go
   :
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 のテストはまだまだ奥深い。時間をとってしっかり学ぶべきやな。常にテスト駆動でコードが書けるようになりたい。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?