web-dev-qa-db-fra.com

Comment appliquer des tests d'intégration (plutôt que des tests unitaires) à une API Flask RESTful

[Selon https://stackoverflow.com/a/46369945/1021819 , le titre doit faire référence aux tests d'intégration plutôt qu'aux tests unitaires]

Supposons que je veuille tester les éléments suivants 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)

Après avoir enregistré ceci en tant que flaskapi.py Et l'exécuter, dans le même répertoire j'exécute le script 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()

Les deux tests réussissent, mais pour le second test (défini dans la classe TestFlaskApi), je n'ai pas encore trouvé comment affirmer que la réponse JSON est telle que prévue (à savoir, {'hello': 'world'}). En effet, il s’agit d’une instance de flask.wrappers.Response (Qui est probablement essentiellement un objet Réponse de Werkzeug (cf. http://werkzeug.pocoo.org/docs/0.11/wrappers/ ) ), et je n’ai pas pu trouver d’équivalent de la méthode json() pour requestsResponse object.

Comment puis-je faire des assertions sur le contenu JSON de la seconde response?

21
Kurt Peek

J'ai constaté que je pouvais obtenir les données JSON en appliquant json.loads() à la sortie de la méthode get_data():

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()

Les deux tests réussissent comme souhaité:

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

OK
[Finished in 0.3s]
25
Kurt Peek

Flask fournit un client test_ que vous pouvez utiliser dans vos tests:

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>

documentation de test de flacon

32
TheGrimmScientist

Ce que vous faites n’est pas un test unitaire. Dans tous les cas, lorsque vous utilisez la bibliothèque de requêtes ou le client flask, vous exécutez test d'intégration , vous effectuez des appels http réels sur les ordinateurs d'extrémité et testez l'interaction.

Le titre de la question ou l'approche est inexacte.

18
Luisa Emme

Avec Python3, j'ai eu l'erreur TypeError: the JSON object must be str, not bytes. Il est nécessaire de décoder:

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

Cette question donne une explication.

2
pylipp