favclip/testeratorを使ってGAE/Goのテストを高速化する

testeratorはGAE/Goのテストを高速化するライブラリです。
このライブラリを使ってテストの高速化ができたので紹介したいと思います。

contextを必要とするテストでは aetest.NewContext()aetest.NewInstance() を使うかと思いますが、これを使うと goapp test実行時にローカルサーバーが関数ごとに起動し、遅くなってしまいます。

func TestHoge(t *testing.T) {
    ctx, done, err := aetest.NewContext() // ローカルサーバー起動
    if err != nil {
        t.Fatal(err)
    }
    defer done()

    // 略
}

func TestFuga(t *testing.T) {
    inst, err := aetest.NewInstance(&aetest.Options{StronglyConsistentDatastore: true}) // ローカルサーバー起動
    if err != nil {
        return nil, nil, err
    }
    req, err := inst.NewRequest("GET", "/", nil)
    if err != nil {
        inst.Close()
        return nil, nil, err
    }
    ctx := appengine.NewContext(req)
    defer inst.Close()

    // 略
}

テストの数が多くなってくると、結構ストレスが溜まります。。。

ここで使うのが testeratorです github.com

testeratorはテスト間でインスタンスを使い回すことができるため、テストが高速化できるという仕組みです。
では、実際に使っていきます。

import (
    "fmt"
    "os"
    "testing"

    "github.com/favclip/testerator"
    _ "github.com/favclip/testerator/datastore"
    _ "github.com/favclip/testerator/memcache"
    _ "github.com/favclip/testerator/search"
)

func TestMain(m *testing.M) {
    if _, _, err := testerator.SpinUp(); err != nil {
        fmt.Printf("testerator.SpinUp error: %v", err)
        os.Exit(1)
    }

    status := m.Run()

    if err := testerator.SpinDown(); err != nil {
        fmt.Printf("testerator.SpinDown error: %v", err)
        os.Exit(1)
    }

    os.Exit(status)
}

func TestHoge(t *testing.T) {
    instance, ctx, err:= testerator.SpinUp()
    if err != nil {
        t.Fatal(err)
    }
    defer testerator.SpinDown()

    // 略
}

func TestFuga(t *testing.T) {
    instance, ctx, err := testerator.SpinUp()
    if err != nil {
        t.Fatal(err)
    }
    defer testerator.SpinDown()

    // 略
}

これだけです。 TestMainm.Run で各テストを実行していきます。
僕はTestMainを書くのを忘れていて、あれ...全然早くならないぞ...と少し悩んだので忘れないようにしましょう。

If you want to clean up Datastore or Search API or Memcache, You should import above packages.

とGoDocに書いてあるように、必要に応じてimportしておきましょう。

contextやinstanceを必要とする全てのテストを書き換えた結果、改善前の時間より 約30% 短縮することができました

まとめ

  • aetest.NewContext()aetest.NewInstance() はテスト関数ごとにローカルサーバーが起動するので遅い
  • testeratorでインスタンスを使い回すことでテストの時間を30%短縮できた