web-dev-qa-db-ja.com

Goのテストパッケージを使用してテストセットアップを行う方法

テストパッケージ を使用しているときに、すべてのテストのステージを設定するテストセットアップ処理全体を実行するにはどうすればよいですか?

Nunitの例として、[SetUp]属性があります。

[TestFixture]
public class SuccessTests
{
  [SetUp] public void Init()
  { /* Load test data */ }
}
72
miltonb

Go 1.4以降では、セットアップ/ティアダウンを実装できます(各テストの前後に関数をコピーする必要はありません)。ドキュメントの概要は、Mainセクションの here にあります。

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は必要ありませんが、必要な場合には歓迎すべき追加機能です。

115
Salvador Dali

これは、_test.goファイルにinit()関数を配置することで実現できます。これは、init()関数の前に実行されます。

// package_test.go
package main

func init() {
     /* load test data */
}

_test.init()は、パッケージのinit()関数の前に呼び出されます。

35
miltonb

単体テストの簡単な関数を考えます:

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
% 

このアプローチでは、追加のパラメーターをセットアップ/分解に渡すことができます。

19
Kare Nuorteva

通常、goのテストは他の言語と同じスタイルで記述されていません。多くの場合、テスト関数は比較的少ないですが、それぞれにテストケースのテーブル駆動セットが含まれています。 Goチームの1人が書いたこの記事 を参照してください。

テーブル駆動テストでは、テーブルに指定された個々のテストケースを実行するループの前にセットアップコードを配置し、その後クリーンアップコードを配置するだけです。

テスト関数間でセットアップコードを共有している場合、共有セットアップコードを関数に抽出し、一度だけ実行することが重要な場合はsync.Onceを使用できます(または別の答えが示すように、init()を使用しますが、テストケースが実行されていなくてもセットアップが行われるという欠点があります(おそらく、go test -run <regexp>を使用してテストケースを制限したためです)。

正確に一度実行される異なるテスト間でセットアップを共有する必要があると思われる場合、本当に必要なのか、テーブル駆動テストが良くないのかを考える必要があります。

12
Paul Hankin

Goテストフレームワークには、NUnitの SetUp属性 (スイート内の各テストの前に呼び出される関数をマークする)に相当するものはありません。ただし、いくつかのオプションがあります。

  1. 必要な各テストからSetUp関数を呼び出すだけです。

  2. XUnitパラダイムと概念を実装するGoのテストフレームワークの拡張機能を使用します。 3つの強力なオプションが思い浮かびます。

これらの各ライブラリは、テストを他のxUnitフレームワークと同様のスイート/フィクスチャに編成することを推奨し、Test*メソッドのそれぞれの前にスイート/フィクスチャタイプのセットアップメソッドを呼び出します。

7