handy-spannerを使ってspannerのテストをしよう


はじめに

こんにちわ、すえけん(@sueken5)です。この記事ではspannerのエミュレータであるhandy-spannerを使ってspannerのコードをテストするやり方を紹介します。

handy-spanner

handy-spannerはgcpugで管理されているプロジェクトで非公式ではありますがspannerをエミュレートするツールです(リンク)。

できることとできないことがREADME.mdに書かれているのでチェックしておきましょう。

built in server

handy-spannerはgolangで書かれていてテストプロセスの中でエミュレータを起動して使うことができます。なのでDockerなどを用意する必要がないためとても簡単にテストできます。


//https://github.com/gcpug/handy-spanner/blob/master/fake/example_test.goより抜粋

func ExampleSpannerClient() {
    ctx := context.Background()
    dbName := "projects/fake/instances/fake/databases/fake"

    // Run fake server
    srv, conn, err := fake.Run()
    if err != nil {
        log.Fatal(err)
    }
    defer srv.Stop()
    defer conn.Close()

    // Prepare spanner client
    client, err := spanner.NewClient(ctx, dbName, option.WithGRPCConn(conn))
    if err != nil {
        log.Fatalf("failed to connect fake spanner server: %v", err)
    }

    // Use the client
    _, _ = client.Apply(ctx, []*spanner.Mutation{
        spanner.Insert("Test",
            []string{"ColA", "ColB"},
            []interface{}{"foo", 100},
        ),
    })

    // output:
}

実際のテストコード


//init_test.go
package spanner_test

import (
    "fmt"
    "log"
    "os"
    "testing"

    "github.com/gcpug/handy-spanner/fake"
    "google.golang.org/grpc"
)

var (
    testServer     *fake.Server
    testConnection *grpc.ClientConn
)

func TestMain(m *testing.M) {
    fmt.Println("test main")

    // Run fake server
    server, conn, err := fake.Run()
    if err != nil {
        log.Fatal(err)
    }

    defer server.Stop()
    defer conn.Close()

    testServer = server
    testConnection = conn

    ret := m.Run()
    os.Exit(ret)
}

TestMainでhandy-spannerサーバーを起動しておきます。


func TestGet_OK(t *testing.T) {
    databaseID := "get-ok"
    dbName := fmt.Sprintf(dbFormat, projectID, instanceID, databaseID)

    ctx := context.Background()
    testCase := struct {
        input  []byte
        key    string
        expect []byte
    }{
        input:  []byte("OK"),
        key:    "test",
        expect: []byte("OK"),
    }

    if err := createDatabase(context.Background(), dbName); err != nil {
        panic(err)
    }

    //fakeサーバー起動時に渡されたコネクションを使ってクライアント生成
    client, err := spanner.NewClient(ctx, dbName, option.WithGRPCConn(testConnection))
    require.Nil(t, err)

    s := &spanner.Store{
        PKey:  testCase.key,
        Value: testCase.input,
    }

    mut := s.Insert(ctx)
    _, err = client.Apply(ctx, []*libspanner.Mutation{mut})
    require.Nil(t, err)

    actual, err := Get(ctx, testCase.key)
    require.Nil(t, err)
    assert.Equal(t, testCase.expect, actual)
}

TestMainでサーバーを起動した時に生成されたコネクションを使ってspannerのクライアントを生成します。あとはいつも通りテストするだけです。

まとめ

簡単にテストできたのでとてもよかったです。