概要
docker run --name bigquery-emulator -d -p 9050:9050 -p 9060:9060 ghcr.io/goccy/bigquery-emulator:latest --project=test-proj
対象読者
BigQueryの単体テストやローカルで結合テストを気軽に行ないたい方
はじめに
BigQueryみたいなGCPの機能を使った単体テストやローカルで結合テストするのって面倒ですよね。多人数の開発でGCP上のBigQueryを使おうとすると、他の人も使ってることがあるので、データベースの状態の管理が難しいですからね。
GCP上に自分専用のBigQueryを作れればいいのですが、その場合も接続情報を変更したり、リソースを作成したりで面倒ですよね。
これらの問題を解決するためにBigQueryのエミュレータを使うことをおすすめします。
もう少し細かい説明
コンテナを利用しましょう
概要にはBigQueryのエミュレータの起動方法を記載しました。細かい使い方はこちらを御覧下さい。
利用する際はコンテナをおすすめします。こちらにgoを使ったバイナリインストールの方法がのっていますが、多分ビルドに時間がかかります。ここに単体テストと同一プロセスでBigQuery emulatorのサーバを立ち上げる方法が記載されていたのですが、ビルドに時間がかかってテストが起動できませんでした。多少古めのM1 Mac上でのビルドだったので、もっと新しいのならば実行可能かもしれませんが、一応、コンテナを使うことをおすすめしておきます。
BigQuery clientを使ったgolangの単体テスト
最後にBigQuery clientを使ったgolangの単体テストを書きます。
bigquery-emulatorは --data-from-yaml
引数でyamlファイルを渡すと、起動した時点でテーブルの作成と初期データの登録を行ってくれます。ただし、単体テストではテスト毎にデータベースは綺麗にしておきたいと思うので、テスト上でテーブル作成とデータ登録することをおすすめします。
テストを実行するまえに、bigquery-emulatorのコンテナを起動しておいてください。
以下にBigQuery clientでdataset、テーブルを作成するコードを記載します。
package main
import (
"context"
"testing"
"cloud.google.com/go/bigquery"
"google.golang.org/api/option"
)
type Data struct {
IntData int64 `bigquery:"int_data"`
StrData string `bigquery:"str_data"`
JsonData string `bigquery:"json_data"`
}
func Test_UseBigQuery(t *testing.T) {
ctx := context.Background()
// Setup client.
client, err := bigquery.NewClient(
ctx,
"test-proj",
option.WithEndpoint("http://localhost:9050"),
option.WithoutAuthentication(),
)
if err != nil {
t.Fatal(err)
}
defer client.Close()
// Create dataset.
dataSet := client.Dataset("my_dataset")
if err := dataSet.Create(ctx, nil); err != nil {
t.Fatal(err)
}
defer dataSet.Delete(ctx)
// Create table.
table := dataSet.Table("my_table")
if err := table.Create(ctx, &bigquery.TableMetadata{
Schema: bigquery.Schema{
{Name: "int_data", Type: bigquery.IntegerFieldType},
{Name: "str_data", Type: bigquery.StringFieldType},
{Name: "json_data", Type: bigquery.JSONFieldType},
},
}); err != nil {
t.Fatal(err)
}
defer table.Delete(ctx)
// Insert data.
if _, err := client.Query(`INSERT INTO test-proj.my_dataset.my_table
(int_data, str_data, json_data)
VALUES (1, 'foo', JSON '{"bar": "baz"}')`).Read(ctx); err != nil {
t.Fatal(err)
}
// Read data.
iter, err := client.Query(`SELECT int_data, str_data, json_data FROM test-proj.my_dataset.my_table`).Read(ctx)
if err != nil {
t.Fatal(err)
}
m := Data{}
err = iter.Next(&m)
if err != nil {
t.Fatal(err)
}
// Occur error to show what we got.
t.Error(m)
}
まとめ
bigquery-emulatorを紹介し、コンテナの起動方法と単体テストの例を記載しました。
client作成部分からテーブル作成部分までを単体テストの例に記載しました。ここの部分を利用していただければbigquery-emulatorにアクセスする単体テストを実装できます。
今後は、テーブル作成までを実行するユーティリティ関数を作ってgithubに起きたいなとおもっています。
素晴しいソフトウフェアを作成して下さったgoccyさんに感謝です。