https://qiita.com/marnie_ms4/items/d5233045a084cebeea14

go1.7からSubTestsが使えるようになったのだけど、 使っていなかったので、調べがてら、その紹介とメモ。 あと、ついでにTableDrivenTestについて書いておく。

Subtestsとは

Subtestsの追加によって、テストに階層を作ることができるようになりました。Runメソッドを使ってテスト内に小さなテストを書いてみます。

コード例

package main

import "fmt"

func Example(name string) string {
    if name == "" {
        return "blank name"
    }
    return fmt.Sprintf("Hello %s", name)
}

func TestExample(t *testing.T) {
    t.Run("case Empty", func(t *testing.T) {
        result := Example("")
        expected := "blank name"
        if expected != result {
            t.Fatalf("failed Test")
        }
    })
    t.Run("case Normal", func(t *testing.T) {
        result := Example("John")
        expected := "Hello John"
        if expected != result {
            t.Fatalf("failed Test")
        }
    })
}

t.Run内でPararell()を使った並行テストも可能です。

サブテストの含まれるテスト関数を実行すれば良いだけです。 ドキュメントを見る限り、以下のような、オプションによるマッチングによって特定のサブテスト だけを実行することも可能です。

go test -run Foo/A=  # For top-level tests matching "Foo", run subtests matching "A=".

Fooを含むトップレベルテスト(通常のテスト関数)内でA=を含むサブテストを実行する。

go test -run /A=1    # For all top-level tests, run subtests matching "A=1".

A=1を含むサブテストを実行する。

$ go test ./...
--- FAIL: TestExample (0.00s)
    --- FAIL: TestExample/case_Empty (0.00s)
        hoge_test.go:12: failed Test
    --- FAIL: TestExample/case_Normal (0.00s)
        hoge_test.go:19: failed Test

失敗させると。第1引数で指定した名前を出してくれますね。

Benchmarkでも使える。

testing.Bでも使えますので、Benchmarkについても階層化が可能です。 こちらはまぁ便利な気もする。

正直、個人的にはこれを待っていたよ!って感動を覚えるものではありませんでした。

というのも、階層が必要なほど複雑なテストが必要な場合はテスト対象コードの仕事が多すぎる気がしますし 1Test1Assertionで育ったこともあり、テスト関数自体を分けてしまうスタンスでしたので。 GoではErrorのような、処理自体は継続する事ができるので、Assertion Roulete のような事はないと 思うのですが、一つのテスト関数に複数を盛り込んで長くするのが、そもそも苦手なのもあり。

うーん。すごく複雑なテストケースが必要な場合もあるのかもしれないし、 見てみたさがあります。求む、エレガントな使用ケース (切実)