回答:
Go 1.4以降では、セットアップ/ティアダウンを実装できます(各テストの前後に関数をコピーする必要はありません)。ドキュメントは概説され、ここでメインセクション:
TestMainはメインのゴルーチンで実行され、m.Runの呼び出しの前後に必要なセットアップとティアダウンを実行できます。次に、m.Runの結果でos.Exitを呼び出す必要があります
これは、テストに関数が含まれている場合、テストfunc TestMain(m *testing.M)
を実行する代わりにこの関数が呼び出されることを意味することを理解するのに少し時間がかかりました。この関数では、テストの実行方法を定義できます。たとえば、グローバルセットアップとティアダウンを実装できます。
func TestMain(m *testing.M) { setup() code := m.Run() shutdown() os.Exit(code) }
他のいくつかの例がここにあります。
最新のリリースでGoのテストフレームワークに追加されたTestMain機能は、いくつかのテストユースケースのためのシンプルなソリューションです。TestMainは、セットアップとシャットダウンの実行、テスト環境の制御、子プロセスでの異なるコードの実行、またはテストコードによってリークされたリソースのチェックを行うためのグローバルフックを提供します。ほとんどのパッケージはTestMainを必要としませんが、必要な場合は歓迎すべき追加です。
lstat $GOROOT/subtests: no such file or directory
これは、init()
関数を_test.go
ファイルに入れることで実現できます。これはinit()
関数の前に実行されます。
// package_test.go
package main
func init() {
/* load test data */
}
_test.init()は、パッケージのinit()関数の前に呼び出されます。
[TestFixtureSetUp]
代わりにNUnitの属性を使用することに多少近いものです。
単体テストする単純な関数があるとします。
package math
func Sum(a, b int) int {
return a + b
}
ティアダウン関数を返すセットアップ関数でテストできます。また、setup()を呼び出した後、teardown()に遅延呼び出しを行うことができます。
package math
import "testing"
func setupTestCase(t *testing.T) func(t *testing.T) {
t.Log("setup test case")
return func(t *testing.T) {
t.Log("teardown test case")
}
}
func setupSubTest(t *testing.T) func(t *testing.T) {
t.Log("setup sub test")
return func(t *testing.T) {
t.Log("teardown sub test")
}
}
func TestAddition(t *testing.T) {
cases := []struct {
name string
a int
b int
expected int
}{
{"add", 2, 2, 4},
{"minus", 0, -2, -2},
{"zero", 0, 0, 0},
}
teardownTestCase := setupTestCase(t)
defer teardownTestCase(t)
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
teardownSubTest := setupSubTest(t)
defer teardownSubTest(t)
result := Sum(tc.a, tc.b)
if result != tc.expected {
t.Fatalf("expected sum %v, but got %v", tc.expected, result)
}
})
}
}
Goテストツールは、シェルコンソールにログステートメントを報告します。
% go test -v
=== RUN TestAddition
=== RUN TestAddition/add
=== RUN TestAddition/minus
=== RUN TestAddition/zero
--- PASS: TestAddition (0.00s)
math_test.go:6: setup test case
--- PASS: TestAddition/add (0.00s)
math_test.go:13: setup sub test
math_test.go:15: teardown sub test
--- PASS: TestAddition/minus (0.00s)
math_test.go:13: setup sub test
math_test.go:15: teardown sub test
--- PASS: TestAddition/zero (0.00s)
math_test.go:13: setup sub test
math_test.go:15: teardown sub test
math_test.go:8: teardown test case
PASS
ok github.com/kare/go-unit-test-setup-teardown 0.010s
%
このアプローチでは、いくつかの追加パラメーターをセットアップ/ティアダウンに渡すことができます。
通常、goのテストは他の言語と同じスタイルで書かれていません。多くの場合、テスト関数は比較的少ないですが、それぞれにテーブル駆動のテストケースのセットが含まれています。Goチームの1人が作成したこの記事を参照してください。
テーブル駆動テストでは、テーブルで指定された個々のテストケースを実行するループの前にセットアップコードを置き、その後にクリーンアップコードを置くだけです。
テスト関数間で共有セットアップコードがまだある場合は、共有セットアップコードを関数に抽出し、sync.Once
それを正確に1回実行することが重要な場合に使用できます(または別の答えが示唆するようにを使用しますinit()
が、これにはセットアップの欠点がありますテストケースが実行されない場合でも実行されます(おそらく、を使用してテストケースを制限したためですgo test -run <regexp>
)。
異なるテスト間で正確に一度だけ実行されるセットアップを共有する必要があると思うなら、本当にそれが必要かどうか、そしてテーブル駆動のテストの方が優れているかどうかについて考えるべきです。
Goテストフレームワークには、NUnitのSetUp属性(スイートの各テストの前に呼び出される関数をマークする)に相当するものはありません。ただし、いくつかのオプションがあります。
SetUp
必要な各テストから関数を呼び出すだけです。
xUnitパラダイムと概念を実装するGoのテストフレームワークの拡張機能を使用します。3つの強力なオプションが思い浮かびます:
これらの各ライブラリは、テストを他のxUnitフレームワークと同様のスイート/フィクスチャに編成することを奨励し、各Test*
メソッドの前にスイート/フィクスチャタイプのセットアップメソッドを呼び出します。
恥知らずなプラグイン、私はこの問題を正確に解決するためにhttps://github.com/houqp/gtestを作成しました。
ここに簡単な例があります:
import (
"strings"
"testing"
"github.com/houqp/gtest"
)
type SampleTests struct{}
// Setup and Teardown are invoked per test group run
func (s *SampleTests) Setup(t *testing.T) {}
func (s *SampleTests) Teardown(t *testing.T) {}
// BeforeEach and AfterEach are invoked per test run
func (s *SampleTests) BeforeEach(t *testing.T) {}
func (s *SampleTests) AfterEach(t *testing.T) {}
func (s *SampleTests) SubTestCompare(t *testing.T) {
if 1 != 1 {
t.FailNow()
}
}
func (s *SampleTests) SubTestCheckPrefix(t *testing.T) {
if !strings.HasPrefix("abc", "ab") {
t.FailNow()
}
}
func TestSampleTests(t *testing.T) {
gtest.RunSubTests(t, &SampleTests{})
}
パッケージ内に任意のテストグループを作成し、それぞれに異なるセットアップ/ティアダウンルーチンのセットを使用できます。