この記事はFirebase Adventcalendar #2の13日目の記事です(もう12/17ですが、丁度書けそうなネタがあったので、空いてる日を見つけて埋めることにしました)。
Firabase Cloud Firestoreを使う場合、Security Rulesがアクセス制御全てのかなめと言えます。ここをミスるとデータが漏れて終わる、しかしその割に簡単に変更できてしまう。というわけで自動テストできると安心でしょう。
今回は先日公開した拙作のBlogFeedback(repo https://github.com/ninjinkun/blog-feedback-app/ )で用いているCircleCIによる自動テスト事例を紹介します。
なお、Security Rulesをテストするというアイデアは以下のエントリから頂きました。
Cloud Firestoreのエミュレーターとテスト用のライブラリが提供されているので、これを利用することでテストを記述・実行できます。エミュレーターの利用はこちらの記事を参考にしました。
firebase-toolsが入っていれば以下でインストールして
firebase setup:emulators:firestore
以下で立ち上げられます。
firebase serve --only firestore
テストの実装
公式のサンプルを参考にfirestore.rulesをテストしていきます。
サンプルではテストはmochaで記述されていますが、今回はcreate-react-appに同梱のJestで記述しました。
アプリ内で使っているRepositoryの関数を呼んで書き込みのテストをしているのと、他人のデータや本来書き込めない領域への書き込みが失敗するテストも記述しました。
src/tests/firebase-rulest.test.tsより一部抜粋
describe('/users/:user_id/blogs', () => {
it('save blog', async () => {
const db = authedApp({ uid: 'ninjinkun' });
firebaseDB.mockReturnValue(db);
await firebase.assertSucceeds(
saveBlog(
'ninjinkun',
'https://ninjinkun.hatenablog.com/',
"ninjinkun's diary",
'https://ninjinkun.hatenablog.com/feed',
'atom'
)
);
});
it('save undefined blog field', async () => {
const db = authedApp({ uid: 'ninjinkun' });
firebaseDB.mockReturnValue(db);
const user = userRef('ninjinkun');
await firebase.assertFails(user.set({ hoge: 'fuga' }));
});
});
ローカルでテストが成功するようになったら、CircleCIの設定へ進みます。
CircleCIでの実行
CircleCIで実行する際のポイントとしては、エミュレータの実行にJavaが必要なため、OpenJDKとNode.js両方が入ったDocker Imageを選ぶことです。今回はとりあえず適当にcircleci/openjdk:11-jdk-sid-node
を選択しました。
余談ですがCloud FunctionsのビルドにはNode.js v6 or v8が必要なため、デプロイ用のjobの方では circleci/node:8.14
を指定してあります。Cloud Functionsのテストも同時に行う場合は、OpenJDK + Node.js v8の組み合わせが入っているDocker Imageを用意する必要があるでしょう。
テストの実行前にエミュレーターのインストールと実行を追記する必要があります。
.circleci/config.ymlから一部抜粋(インストールしたエミュレーターをキャッシュできるとは思うのですが、そんなに時間がかかっているわけでもないのでさぼっています)
- run: yarn firebase setup:emulators:firestore
- run:
command: yarn firebase serve --only firestore
background: true
CIを実行すると以下の様にローカルと同じようにテストが実行されました。これで一安心。
CI実行結果から抜粋
#!/bin/bash -eo pipefail
yarn test:ci
yarn run v1.12.3
$ CI=true react-scripts test --env=jsdom
PASS src/__tests__/save-count-response.test.ts
PASS src/__tests__/firebase-rules.test.ts
PASS src/__tests__/App.test.tsx
Test Suites: 3 passed, 3 total
Tests: 10 passed, 10 total
Snapshots: 0 total
Time: 3.208s
Ran all test suites.
Done in 4.68s.
テストの速度
テストケース10個で以下の通りでした。エミュレーターの起動に18秒かかっているので、ここが一番遅いですね。とりあえず許容範囲内としていますが、他のテストでも時間がかかっているとストレスになるかもしれません。
2019/2/18 追記
firebase-tools > 6.1.1 ではCircleCIでのエミュレータ起動が失敗するので、.jar
の直接起動が必要になりました。そのうち解消されるとは思いますが
具体的な作業は以下に。
Upgrade firebase tools by ninjinkun · Pull Request #54 · ninjinkun/blog-feedback-app · GitHub
2019/6/14 追記