web-dev-qa-db-ja.com

(単体テストではなく)統合テストをFlask RESTful APIに適用する方法

[ https://stackoverflow.com/a/46369945/1021819 に従って、タイトルは単体テストではなく統合テストを参照する必要があります]

次のFlask API(from here )をテストしたいとします。

_import flask
import flask_restful

app = flask.Flask(__name__)
api = flask_restful.Api(app)

class HelloWorld(flask_restful.Resource):
    def get(self):
        return {'hello': 'world'}

api.add_resource(HelloWorld, '/')

if __name__ == "__main__":
    app.run(debug=True)
_

これを_flaskapi.py_として保存して実行したら、同じディレクトリでスクリプト_test_flaskapi.py_を実行します。

_import unittest
import flaskapi
import requests

class TestFlaskApiUsingRequests(unittest.TestCase):
    def test_hello_world(self):
        response = requests.get('http://localhost:5000')
        self.assertEqual(response.json(), {'hello': 'world'})


class TestFlaskApi(unittest.TestCase):
    def setUp(self):
        self.app = flaskapi.app.test_client()

    def test_hello_world(self):
        response = self.app.get('/')

if __name__ == "__main__":
    unittest.main()
_

両方のテストに合格しますが、2番目のテスト(TestFlaskApiで定義)クラスでは、JSON応答が期待どおり(つまり_{'hello': 'world'}_)であることをアサートする方法をまだ理解していません。これは_flask.wrappers.Response_のインスタンスであるためです(おそらく本質的にはWerkzeug Responseオブジェクトです(cf. http://werkzeug.pocoo.org/docs/0.11/wrappers/ )) 、およびrequestsResponse objectのjson()メソッドに相当するものを見つけることができませんでした。

2番目のresponseのJSONコンテンツでアサーションを作成するにはどうすればよいですか?

21
Kurt Peek

json.loads()get_data()メソッドの出力に適用することでJSONデータを取得できることがわかりました。

import unittest
import flaskapi
import requests
import json
import sys

class TestFlaskApiUsingRequests(unittest.TestCase):
    def test_hello_world(self):
        response = requests.get('http://localhost:5000')
        self.assertEqual(response.json(), {'hello': 'world'})


class TestFlaskApi(unittest.TestCase):
    def setUp(self):
        self.app = flaskapi.app.test_client()

    def test_hello_world(self):
        response = self.app.get('/')
        self.assertEqual(
            json.loads(response.get_data().decode(sys.getdefaultencoding())), 
            {'hello': 'world'}
        )


if __name__ == "__main__":
    unittest.main()

両方のテストが必要に応じて合格します。

..
----------------------------------------------------------------------
Ran 2 tests in 0.019s

OK
[Finished in 0.3s]
25
Kurt Peek

Flaskは、テストで使用できるtest_clientを提供します。

from source.api import app
from unittest import TestCase

class TestIntegrations(TestCase):
    def setUp(self):
        self.app = app.test_client()

    def test_thing(self):
        response = self.app.get('/')
        assert <make your assertion here>

Flask Testing Docs

32

そこで行うことは、単体テストではありません。いずれの場合でも、リクエストライブラリまたはflask client)を使用する場合、エンドポイントへの実際のhttp呼び出しを行い、相互作用をテストするときに 統合テスト を実行しています。

質問のタイトルまたはアプローチのいずれかが正確ではありません。

18
Luisa Emme

Python3では、エラーTypeError: the JSON object must be str, not bytes。デコードする必要があります:

# in TestFlaskApi.test_hello_world
self.assertEqual(json.loads(response.get_data().decode()), {'hello': 'world'})

この質問 は説明を与えます。

2
pylipp