Как сделать модульное тестирование для функций внутри класса Resource в flask -restful? - PullRequest
0 голосов
/ 12 апреля 2020

Я довольно новичок в модульном тестировании и относительно новый в разработке RESTful API. Мне интересно, как сделать модульный тест для функций внутри класса Resource в flask restful? Я могу выполнить модульное тестирование ответа конечной точки, но я не знаю, как выполнить тестирование отдельных функций внутри класса контроллера конечной точки.

Ниже приведен код моего приложения. Имеет 3 файла, включая test:

  • api.py
  • controller_foo.py
  • test_controller_foo.py
# api.py

from flask import Flask
from flask_restful import Api

from .controller_foo import ControllerFoo


def create_app(config=None):
    app = Flask(__name__)
    app.config['ENV'] ='development'
    return app

application = app = create_app()
api = Api(app)

api.add_resource(ControllerFoo, '/ctrl')

if __name__ == "__main__":
    app.run(debug=True)
# controller_foo.py

from flask_restful import Resource
from flask import request

class ControllerFoo(Resource):
    """
    basically flask-restful's Resource method is a wrapper for flask's MethodView
    """
    def post(self):
        request_data = self.handle_request()
        response = self.process_request(request_data)
        return response

    def handle_request(self):
        json = request.get_json()
        return json

    def process_request(self, data):
         # do some stuffs here
         return {'foo': 'bar'}

Я использую unittest

# test_controller_foo.py

import unittest

from api import app
from .controller_foo import ControllerFoo

# initiating class to try testing but I don't know how to start
ctrl = ControllerFoo()

class ControllerFooTestCase(unittest.TestCase):
    def setUp(self):
        self.app = app
        self.app.config['TESTING'] = True
        self.client = app.test_client()
        self.payload = {'its': 'empty'}

    def tearDown(self):
        pass

    def test_get_response(self):
        response = self.client.post('/ctrl', json=self.payload)
        expected_resp = {
            'foo': 'bar'
        }
        self.assertEqual(response.status_code, 200)
        self.assertDictEqual(response.get_json(), expected_resp)

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

Я хочу знать, как правильно выполнить модульное тестирование для handle_request и process_request функции

РЕДАКТИРОВАТЬ: Исправление моего глючного кода. Спасибо Laurent LAPORTE за основные моменты.

1 Ответ

1 голос
/ 12 апреля 2020

В вашем коде есть несколько ошибок, поэтому это нелегко объяснить.

Прежде всего, рекомендуется использовать тестирование с Flask (и Flask -Restful) PyTest вместо unittest , потому что его проще в настройке и использовании.

Ознакомьтесь с документацией: Тестирование Flask Приложения .

Но вы можете начать с unittest…

примечание: вы можете запутаться с вашим модулем app и экземпляром app в этом модуле. Итак, чтобы избежать этого, я импортировал модуль. Еще одна хорошая практика - назовите свой тестовый модуль по отношению к протестированному модулю: "app.py" => "test_app.py". У вас также может возникнуть путаница с модулем controller и экземпляром controller. Лучше всего использовать более точное имя, например «controller_foo» или что-то еще…

Вот тест работающего модуля:

# test_app.py

import unittest

import app


class ControllerTestCase(unittest.TestCase):
    def setUp(self):
        self.app = app.app
        self.app.config['TESTING'] = True
        self.client = self.app.test_client()
        self.payload = {'its': 'empty'}

    def test_get_response(self):
        response = self.client.post('/ctrl', json=self.payload)
        expected_resp = {'foo': 'bar'}
        self.assertEqual(response.status_code, 200)
        self.assertDictEqual(response.get_json(), expected_resp)


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

Как вы можете видеть, я также исправил опубликованный URL-адрес, в вашем приложении URL-адрес «/ ctrl», а не «controller».

На этом этапе тест можно запустить, но у вас есть другая ошибка:

Ran 1 test in 0.006s

FAILED (errors=1)

Error
Traceback (most recent call last):
  ...
TypeError: process_request() takes 1 positional argument but 2 were given

Если вы посмотрите на метод process_request(), вы увидите, что пропустили параметр self. Измените его следующим образом.

    def process_request(self, data):
        # do some stuffs here
        return {'foo': 'bar'}

Ваш тест должен пройти.

Но это не правильный способ реализации Flask -Restful контроллеров. Прочитайте do c и используйте get и post методы…

...