LoginSignup
3
3

More than 3 years have passed since last update.

python×Cloud Functions×FirestoreでAPIを簡単に作ってみる Pt2 テスト編(詳細)

Last updated at Posted at 2019-08-04

概要

Firestoreのデータ操作を行う関数をローカルでテストするためのあれこれをまとめます。やり方としては、Flaskのrequestオブジェクトを使ってローカルにAPIを作成します。

開発環境

  • 開発環境
    • MacOS
    • python3.7
    • pycharm

新規プロジェクトの作成

pycharmまたはpyvenvコマンドを用いて新規プロジェクトを作成します。画面イメージはpycharmですが、デフォルトで作成されるフォルダに加えて「.auth」「functions」も作成しています。また、ファイルは省略します。

スクリーンショット 2019-08-04 16.17.56.png

関数の作成

テストする関数はPt1と同じです。functions/に置きます。

functions/getFilteredUser.py

import json
from google.cloud import firestore

# ソースはPt1と同じ
def get_filtered_user(request):

    request_json = request.get_json()
    if request.args and 'name' in request.args:
        request_name = request.args.get('name')
    elif request_json and 'name' in request_json:
        request_name = request_json['name']
    else:
        request_name = ''

    db = firestore.Client()

    query = db.collection('user').where('name', '==', request_name)
    docs = query.get()
    users_list = []
    for doc in docs:
        users_list.append(doc.to_dict())
    return_json = json.dumps({"users": users_list}, ensure_ascii=False)

    return return_json

ローカルにAPIを作る

Cloud FunctionsではFlaskのrequestオブジェクトを使って、リクエスト条件が関数に受け渡しされます。なので、ローカルにFlaskを使ってAPIを作ることで、テスト可能になります。

以下のようなソースを作ります。

localServer.py

from flask import Flask, request, abort, render_template, send_from_directory
# 作成した関数を外部ソースからimport
from functions.getFilteredUser import get_filtered_user

app = Flask(__name__)

# methodにPOST等も明示的に指定(FlaskではデフォルトGETのみのため)
# '/~'がテストするときのパス
@app.route('/get-filtered-user', methods=['GET', 'POST'])
def local_api():
    return get_filtered_user(request)

if __name__ == '__main__':
    app.run()

これでhttp://localhost:5000/get-filtered-userにリクエストを投げると、get_filtered_userが実行されるようになります。
但し、関数がローカルからFirebaseにアクセスするには、秘密鍵を環境変数に読み込ませる必要があります。

秘密鍵の取得・設定

秘密鍵の取得方法は以下のいずれかのページがわかりやすいです。

Cloud FirestoreのデータをPythonで取得する
Firebase公式 - SDK の初期化

取得したファイルのパスを、GOOGLE_APPLICATION_CREDENTIALSの環境変数に設定することでローカルからのFirestoreへのアクセスが可能になります。環境変数の設定は以下のような方法があります。

[方法1] pycharmの「構成の編集>環境変数」から追加
pycharmではこのやり方が使えます。ソースごとに環境変数が設定可能なので、複数のFirebaseプロジェクトを扱う場合でも、bash_profileを書き換える必要がなくなります。
スクリーンショット 2019-07-17 1.03.38.png

この例では「.auth/firebase_auth.json」という秘密鍵ファイルを読み込ませています。

[方法2] ターミナルから環境変数を設定

MacOS
$ export GOOGLE_APPLICATION_CREDENTIALS="<保存先>/<秘密鍵ファイル>.json"
# .bash_profileに追記する場合 (ターミナルの再起動が必要)
$ echo 'export GOOGLE_APPLICATION_CREDENTIALS="<保存先>/<秘密鍵ファイル>.json"' >> ~/.bash_profile

作成したソースをターミナルからpython sample.pyと実行する場合、このやり方が一番シンプルです。

[方法3] pythonのソースにベタ書き

os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "<保存先>/<秘密鍵ファイル>.json"

ソースの中に書きたい事情がある場合はこれでもいけると思います。

ディレクトリの最終状態

functionsと.authを含めて以下の状態になっているはず。functions/getUser.pyはPt1のソースが残ってるだけなので無くても問題ありません。
スクリーンショット 2019-08-04 16.23.48.png

ローカルでのテスト

環境変数を設定した状態で、localServer.pyを実行してhttp://localhost:5000/get-filtered-userにリクエストを投げます。

localServer.pyの実行
$ python localServer.py
 * Serving Flask app "localServer" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [04/Aug/2019 14:51:35] "POST /get-filtered-user HTTP/1.1" 200 -

ローカルでの関数テスト
$ curl -X POST -H "Content-Type: application/json" -d '{"name": "Alice"}' http://localhost:5000/get-filtered-user
{"users": [{"age": 19, "name": "Alice", "gender": "female"}]}

これで、Cloud Functionsにデプロイせずともテストできるようになりました。デプロイすると2分ほど待ちますが、この方法だとすぐにテストできます。localServer.pyのコンソールにはprintの内容が出力されるのでデバッグも容易になります。

また、pycharmの場合、pythonの実行とターミナルを並べて実行すれば便利です。
スクリーンショット 2019-08-04 15.22.04.png

もちろんPostmanを使ってもOKです。

おわりに

Cloud Functionsではいきなりデプロイするのではなく、以下のような流れでコードを作成すると、どこでバグってるかがわかりやすいので、ハマることが少なく開発できると思います。

  1. デプロイしたい関数だけでテスト
  2. ローカルにAPIを作成してテスト
  3. Cloud Functionsにデプロイ

1では、リクエスト条件などをベタ書きで書いてみて、関数が想定通り動くか確認します。2では、GETやPOSTでリクエストが渡された時の動きを確認できます。

今回は、この中の2のやり方を書きました。

Pt3では、3のデプロイをローカルから行う方法を書こうと思います。

参考リンク

How to develop Python Google Cloud Functions
ローカルでの関数の実行
MacでCloud Machine Learning Engineを利用してみる

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3