Help us understand the problem. What is going on with this article?

Firestore Emulator を使って GitHub Actions でテストを動かしてみる

この記事は フラー Advent Calendar 2020 の23日目の記事です。
22日目は @ujikawa1026 さんで
小さな開発組織のマネージャーになってから1on1で考えていることを少しだけ書く」でした。

はじめに

はじめまして。
今年の4月から、フラー株式会社のエンジニアとしてアルバイトをさせていただいております。
普段は、サーバーサイドエンジニアとしてGoを用いたAPI開発を行っています。

今回は、Firestore EmulatorとGitHub Actionsによる自動テストを作成したので、記事にまとめてみました。

きっかけ

3ヶ月ほど前にFirestoreとGoで書かれたAPIを作成する機会があり、
ついでにテストも書くことになったので、Github Actionsを使ってテストを自動化することにしました。

本題

今回作成したAPIはDB(Firestore)が絡んだものでした。
当たり前な話かもしれませんが、
テストを行う際に本番環境で使われるDBに接続するのはよく無いです。テストによってDBの中身に変更が加わったり、壊れるのを避ける必要があります。

テスト用のDBを用意する

Firestore Emulatorを使用して、テストに用いるDBを作成します。
Emulatorを使うことで、わざわざテスト用にDBを作成する必要がなく、
テストの度に同じ条件のDBをEmulatorに用意することができます。


Emulatorはgcloudコマンドを使って起動します。
コマンド名は、
gcloud beta emulators firestore
https://cloud.google.com/sdk/gcloud/reference/beta/emulators/firestore

使い方は次の通り

$ gcloud beta emulators firestore start [--host-port=HOST_PORT]

オプションでホスト名とポート番号を指定して、gcloudコマンドを実行することでFirestore Emulatorが起動します。

*注意点として、コマンド名にも書いてありますがbeta版です...

This command is currently in BETA and may change without notice.

使用する場合は、急な仕様変更に注意する必要があります。

Go で Firestore Emulator を使用する

GoでFirestore Emulatorに接続します。
Firestore PackageはEmulatorをサポートしており、GoでEmulatorを使うことができます。

https://godoc.org/cloud.google.com/go/firestore#hdr-Google_Cloud_Firestore_Emulator

This package supports the Cloud Firestore emulator, which is useful for testing and development.



Goでは以下のようにしてFirestoreのクライアントを作成します。

ctx := context.Background()
client, err := firestore.NewClient(ctx, "projectID")
if err != nil {
    // TODO: Handle error.
}

このとき、ホスト名とポート番号をFIRESTORE_EMULATOR_HOSTに定義しておくことで、優先的にEmulatorを接続するようになります。

https://github.com/googleapis/google-cloud-go/blob/e0be520e1a5e36548f82823602aacfd3277cb7e9/firestore/client.go#L64-L77

If this environment variable is defined, configure the client to talk to the emulator.

特にGoの方で明示的にEmulatorに接続する処理を書く必要はないです。

GitHub Actions で Firestore Emulator を起動する

GitHub Actions

.github/workflows/ディレクトリにワークフローファイルを置いておくことで、指定したイベントがトリガーとなってデプロイやテスト、その他様々なアクションを自動で行うことができます。
詳しくはドキュメント参照

今回は自動テストを追加するので、テストを行うワークフローを書いたtest.yamlファイルを.github/workflows/ディレクトリに置いておきます。

SetUp

テストで使用するツールのセットアップを行います。

Goのセットアップ

- name: Set up Go
  uses: actions/setup-go@v1
  with:
    go-version: "1.13"

参考したもの
https://github.com/actions/setup-go
https://github.com/mvdan/github-actions-golang
他にも設定があった気がします。

gcloudとFirestoreのセットアップは以下の通り

- name: setup gcloud
  uses: google-github-actions/setup-gcloud@master
  with:
    version: "latest"

- name: setup firestore emulator
  run: |
    gcloud components install beta --quiet
    gcloud components install cloud-firestore-emulator --quiet

gcloudのセットアップはgoogle-github-actionsのREADMEを参考にしました。

Firestore Emulatorのセットアップは公式に書いてある通りです。
必要なコンポーネントのインストール↓

$ gcloud components install [COMPONENT-ID]

COMPONENT-IDの検索↓

$ gcloud components list

オプションで--quietを指定しないと、インタラクティブモードが有効になって、セットアップが進まないです(たしか..)

Testのフローを追加

最後に、テストを実行するフローを追加します。
今回、テストの作成にはtestingパッケージを使用しました。
https://golang.org/pkg/testing/

テストを実行するには、適切なディレクトリに移動して次のコマンドを実行するだけです。

$ go test ./... 

また、テストを実行する前にEmulatorを起動しておく必要があります。
起動方法は上で書いた通りで、追加するフローは以下の通りです。

- name: Test
  run: |
    gcloud beta emulators firestore start --host-port=localhost:8080 &
    curl http://localhost:8080 --silent --retry 30 --retry-delay 1 --retry-connrefused
    go test ./... -v
  env:
    FIRESTORE_EMULATOR_HOST: localhost:8080

curlコマンドの部分では、Emulatorが立ち上がる前にテストが実行されるのを防ぐために、ディレイをかけています。
また、Emulatorに接続させるために、環境変数FIRESTORE_EMULATOR_HOSTを追加しています。


以上で、トリガーとして指定したイベントが発生した特に、Emulatorの起動からテストの実行まで自動で行ってくれるようになると思います。
ちなみに私は、プッシュするたびにテストが走るように設定しておきました。

最後に

初めて書きました。
次回(?)は、もっと綺麗にわかりやすく書けたらなと思います。

あと、ここ違う!とか、こうした方が良さそう
っていうところがあったら、指摘していただけると助かります:bow:

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away