doc.dev1x.org

Golangテスト周りに関する覚書

基本的なテストコード

package mypackage

func MyFunction(s string) string {
    return s + s
}
package mypackage

import (
    "testing"
)

func TestMyFunction(t *testing.T) {
    input := "わーい"
    got := MyFunction(input)
    want := "わーいわーい"
    if got != want {
        t.Errorf("got:%s want: %s", got, want)
    }
}

テストの実行

全てのテストを実行

go test

パッケージ単位で実行

関数単位で実行

ファイル名を指定して実行

カバレッジの計測

ベンチマークの計測

ビルドタグによるテスト対象の制御

並列実行

テストコードを書く

前処理/後処理

並列実行

テストをスキップ

Exampleテスト

テストデータ

テストコードのパッケージ

ヘルパー関数

func helperFunction(t *testing.T, s string) string {
    t.Helper()  //
    u, err := url.Parse(s)
    if err != nil {
        t.Fatal(err)
    }
    return u
}
func TestHello(t *testing.T) {
    message := "ieeeeeee"
    result := Echo(message)
    expext := message
    if result != expext {
        t.Error("\n実際: ", result, "\n理想: ", expext)
    }
    t.Cleanup(func() {
        t.Log("Cleanup")
    })
}

T.Error

テーブル駆動テスト

非公開関数をテストする

benchmark

便利ライブラリ

参考資料

Appendix-1

 type T
    func (c *T) Cleanup(f func())
    func (t *T) Deadline() (deadline time.Time, ok bool)
    func (c *T) Error(args ...interface{})
    func (c *T) Errorf(format string, args ...interface{})
    func (c *T) Fail()
    func (c *T) FailNow()
    func (c *T) Failed() bool
    func (c *T) Fatal(args ...interface{})
    func (c *T) Fatalf(format string, args ...interface{})
    func (c *T) Helper()
    func (c *T) Log(args ...interface{})
    func (c *T) Logf(format string, args ...interface{})
    func (c *T) Name() string
    func (t *T) Parallel()
    func (t *T) Run(name string, f func(t *T)) bool
    func (t *T) Setenv(key, value string)
    func (c *T) Skip(args ...interface{})
    func (c *T) SkipNow()
    func (c *T) Skipf(format string, args ...interface{})
    func (c *T) Skipped() bool
    func (c *T) TempDir() string

T.Cleanup

func TestHello(t *testing.T) {
    message := "ieeeeeee"
    result := Echo(message)
    expext := message
    if result != expext {
        t.Error("\n実際: ", result, "\n理想: ", expext)
    }
    t.Cleanup(func() {
        t.Log("Cleanup")
    })
}

Appendix-2 テストコードサンプル

// テスト関数
func Test(t *testing.T) {
    // テスト対象の初期化関数
    initModel := func() *Model {
        return &Model{
            Name: "TEST"
            Age:  0
        }
    }
    tests := []struct {
        name   string           // テストケース名
        model  func() *Model    // テスト対象を加工する関数
        want   bool             // 期待値
    }{
        {
            name:  "testCase_1",
            model: func() *Model {
                // ベースとなるモデルを取得
                model := initModel()
                // テスト内容に応じて加工
                model.Age = 18
                // 返却
                return model
            },
            want: false,
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            // テスト対象を取得
            model := tt.model()
            // 検証
            got := model.IsAdult()
            if got != tt.want {
                t.Error("Error")
            }
        })
    }
}