この記事は フラー 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を使うことができます。
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を接続するようになります。
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の起動からテストの実行まで自動で行ってくれるようになると思います。
ちなみに私は、プッシュするたびにテストが走るように設定しておきました。
#最後に
初めて書きました。
次回(?)は、もっと綺麗にわかりやすく書けたらなと思います。
あと、ここ違う!とか、こうした方が良さそう
っていうところがあったら、指摘していただけると助かります