いろいろ備忘録日記

主に .NET とか Go とか Python絡みのメモを公開しています。

Goメモ-136 (Exampleテストで非同期結果をテストする)

概要

よく忘れるのでメモメモ。

Goには Example関数名 という形でテスト関数を作ると、ドキュメントに使用例として載ってくれる、かつ、ついでにテストとしても利用できる機能があります。

こんな感じですね。

func Xx() string {
    return "hello"
}

// 関数 XX の使用例。
func ExampleXx() {
    fmt.Println(Xx())

    // Output:
    // hello
}

関数の下部にコメントで

// Output:

を書いて、次の行から標準出力に出力される内容を記載します。

テスト時にこの出力と合致したら成功、合致しない場合は失敗となります。

Pythonのdoctestに似ていて、私自身はよくこれでテスト書きます。

その関数が非同期処理する関数の場合

通常時は、上記のような形で書けば良いのですが、非同期処理する関数の例を書く場合、当然結果は非同期となります。

なので、決まった形で出力されないケースが多いです。

そのようなときは、以下のようにコメントを書いて結果を書くと非同期結果を確認できます。

// Unordered output:

以下、サンプルです。

まずは、非同期関数の結果を同期のように書いて失敗するパターン。

下記処理で出てくる Generator とか FanIn とかの関数は以前の記事で書いたチャネル関数です。

まあ、非同期する関数と思ってください。

devlights.hatenablog.com

devlights.hatenablog.com

func ExampleFanIn() {
    var (
        rootCtx          = context.Background()
        mainCtx, mainCxl = context.WithCancel(rootCtx)
        procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
    )

    defer mainCxl()
    defer procCxl()

    numStream1 := chans.Generator(procCtx.Done(), 1, 2, 3)
    numStream2 := chans.Generator(procCtx.Done(), 4, 5, 6)

    for v := range chans.FanIn(procCtx.Done(), numStream1, numStream2) {
        fmt.Println(v)
    }

    // Output:
    // 1
    // 2
    // 3
    // 4
    // 5
    // 6
}

gomy/example_test.go at master · devlights/gomy · GitHub

実行すると、以下のように失敗します。

codespace ➜ /workspaces/gomy (master) $ go test ./chans -run ^ExampleFanIn$
--- FAIL: ExampleFanIn (0.00s)
got:
1
4
2
3
5
6
want:
1
2
3
4
5
6
FAIL
FAIL    github.com/devlights/gomy/chans 0.003s
FAIL

当然ながら、結果が合わないですね。

んで、これを Unordered output: にしてみましょう。

func ExampleFanIn() {
    var (
        rootCtx          = context.Background()
        mainCtx, mainCxl = context.WithCancel(rootCtx)
        procCtx, procCxl = context.WithTimeout(mainCtx, 50*time.Millisecond)
    )

    defer mainCxl()
    defer procCxl()

    numStream1 := chans.Generator(procCtx.Done(), 1, 2, 3)
    numStream2 := chans.Generator(procCtx.Done(), 4, 5, 6)

    for v := range chans.FanIn(procCtx.Done(), numStream1, numStream2) {
        fmt.Println(v)
    }

    // Unordered output:
    // 4
    // 1
    // 5
    // 2
    // 3
    // 6
}

gomy/example_test.go at master · devlights/gomy · GitHub

再度、実行してみます。

codespace ➜ /workspaces/gomy (master) $ go test ./chans -run ^ExampleFanIn$
ok      github.com/devlights/gomy/chans 0.003s

今度は成功になりました。Unordered output: をつけたことにより結果の順序は問わないようになったので成功判定されています。

参考資料

golang.org


過去の記事については、以下のページからご参照下さい。

  • いろいろ備忘録日記まとめ

devlights.github.io

サンプルコードは、以下の場所で公開しています。

  • いろいろ備忘録日記サンプルソース置き場

github.com

github.com

github.com