dak ブログ

python、rubyなどのプログラミング、MySQL、サーバーの設定などの備忘録。レゴの写真も。

unittest での Flask のテスト

2022-07-29 21:21:13 | python
unittest で Flask の request を含むプログラムを unittest でテストする方法のメモ。
プログラムの構成は以下の通りです。
・main.py: Flask のアプリケーション
・app_controller.py: リクエスト処理の本体
・test_app_controller.py: app_controller.py のテストプログラム

test_app_controller.py が unittest を用いた app_controller.py のテストプログラムとなっています。

■main.py
Flask アプリのメインで、リクエストは AppController が処理します。
from flask import Flask, request
from app_controller import AppController

app = Flask(__name__)
gctrl = AppController()

@app.route('/')
def api_sample():
    res_obj, status = gctrl.process_request()
    return res_obj, status

if __name__ == '__main__':
    app.run('0.0.0.0', port=8080)


■app_controller.py
リクエスト処理の本体。
リクエストパラメータの str1 と str2 を連結した文字列をレスポンスのオブジェクトに入れて返却します。
from flask import request

class AppController:
    def create_response(self, str1, str2):
        resp_obj = {
            'message': f"{str1}_{str2}",
        }
        return resp_obj

    def process_request(self):
        str1 = request.args.get('str1', '')
        str2 = request.args.get('str2', '')
        resp_obj = self.create_response(str1, str2)
        status = 200
        return resp_obj, status


■Flask アプリを起動
$ python main.py
...
 * Running on http://127.0.0.1:8080
 * Running on http://192.168.8.129:8080 (Press CTRL+C to quit)


■curl でレスポンスを確認
$ curl 'http://localhost:8080/?str1=abc&str2=def'
{"message":"abc_def"}


■unittest のプログラム(test_app_controller.py)
process_request() は request を利用しているため、app = Flask() で Flask を起動し、
app.test_request_context() でテスト用のリクエストの設定を行います。
import unittest
from flask import Flask, request
from app_controller import AppController

class TestAppController(unittest.TestCase):
    def test_create_response(self):
	ctrl = AppController()
        resp_obj = ctrl.create_response('abc', 'def')
        self.assertEqual(resp_obj['message'], 'abc_def')

    def test_process_request(self):
        with app.test_request_context('/?str1=abc&str2=def') as req:
            ctrl = AppController()
            resp_obj, status = ctrl.process_request()
            self.assertEqual(resp_obj['message'], 'abc_def')
            self.assertEqual(status, 200)

if __name__ == '__main__':
    app = Flask(__name__)
    unittest.main()


■unittest の実行
$ python test_app_controller.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.006s

OK