Vue.js で作ったフィードリーダー で Tweet を取得するための API を Cloud Functions for Firebase で作ってみました。
実装サンプル: GitHub
やりたかったこと
今回は以下の要件とともに Cloud Functions を実装してみました。
- CORS/cache などのミドルウェアを使いたい。
- API エンドポイントとモジュールの単体テストをしたい。
- 自動テストで単体テストを回したい。
API を動かすまでの手順
リポジトリの プロジェクトのセットアップ手順 を補足しながら追っていきます。
必要なもの
-
Twitter API を使うためのクレデンシャル
Twitter Application Management から取得します。 -
Firebase プロジェクトの 料金プラン を有料版に変更
外部 API と通信するため、Flame もしくは Blaze に変更します。 -
Firebase Tools のインストール
-
Firebase Console での Firebase プロジェクト作成
Firebase 環境変数の設定
Twitter のクレデンシャルと API で使用する設定を Firebase CLI で環境変数に設定します。
$ firebase functions:config:set \
credential.twitter.consumer_key="YOUR_CONSUMER_KEY" \
credential.twitter.consumer_secret="YOUR_CONSUMER_SECRET" \
credential.twitter.access_token_key="YOUR_ACCESS_TOKEY_KEY" \
credential.twitter.access_token_secret="YOUR_ACCESS_TOKEY_SECRET" \
... 省略 ...
設定の確認
$ firebase functions:config:get
{
"credential": {
"twitter": {
"consumer_key": "YOUR_CONSUMER_KEY",
"consumer_secret": "YOUR_CONSUMER_SECRET",
"access_token_secret": "YOUR_ACCESS_TOKEY_SECRET",
"access_token_key": "YOUR_ACCESS_TOKEY_KEY",
... 省略 ...
}
}
}
ローカル環境で API を実行する場合は、 {firebase プロジェクトディレクトリ}/functions
ディレクトリ内でコンフィグ用ファイルを作成してから動作を確認しました。
$ firebase functions:config:get > .runtimeconfig.json
$ firebase serve --only functions
API 処理の実装
API エンドポイント処理
今回はやりたかったことの要件を満たしつつユースケースをAPI 処理を実装していきます。
ミドルウェアの使用
今回は、API エンドポイント処理を単体テスト可能にするため、Firebase SDK の Cloud Function エンドポイント処理用のメソッドのコールバック処理内でミドルウェアを指定しています。
パラメータに Express.js のインスタンスを指定する方が簡潔なコードになるのですが、単体テストの書き方がわかりませんでした
const cors = require('cors')({origin:true})
const compression = require('compression')()
...
exports.topics = functions.https.onRequest((request, response) => {
cors(request, response, () => {
compression(request, response, () => {
// API ビジネスロジック
...
Twitter API との連携
ツイートデータのキャッシュ
Twiiter API のリクエストレートリミット対策をしたかったので、ツイートデータを memory-cache モジュールでキャッシュするようにしました。
$ npm install --save memory-cache
ユニットテストで Firebase 環境変数を使う
CI 環境で実行するユニットテストで Firebase 環境設定を取得する方法がわからなかったので、設定取得処理をラップしてモックできるようにしました。
const configModule = new ConfigModule(functions.config())
ユニットテスト
テスト用のフレームワークは Jest を使いました。
{Firebase プロジェクト}/functions
ディレクトリでインストールコマンドを実行したらテストが実行可能になります。
$ npm install --save-dev jest
API やモジュールのテストケースを実装したら実行します。
$ npm test
インテグレーションテスト
今回はユニットテストでは環境設定の取得やモジュールをモックしているので、実際の設定を使用した動作確認はインテグレーションテストのスコープに入れました。CI 環境での自動テストは未設定のため手動で実行しています。
ローカルサーバ起動コマンド
$ firebase serve --only functions
http://localhost:5000/{プロジェクトID}/{リージョン}/topics
にアクセスして Tweet データが表示されるか確認します。
ローカルサーバで API の動作が確認できたら、Vue.js で作ったフィードリーダー の E2E テストでも動作を確認しています。
QA テスト
QA 用の Firebase プロジェクトにデプロイして動作確認をします。
$ firebase deploy --only functions
https://{QA用プロジェクトの公開用サブドメイン}.cloudfunctions.net/topics
にアクセスしてローカルテスト同様の Tweet データが表示されるか確認します。インテグレーションテストと同様にクライアントとの接続テストも確認してみます。