Тестирование валидаторов Flask WTForms без повторения кода - PullRequest
0 голосов
/ 27 октября 2018

Я написал относительно простое веб-приложение, использующее Flask и WTForms со стандартными и настраиваемыми валидаторами форм.Я сейчас пытаюсь научиться тестированию Python.Я написал следующий файл tests.py, который отлично работает с unittest, но имеет избыточность.Есть ли лучший, более эффективный, более питонический (DNRY) способ сделать это?Я посмотрел на некоторые учебники по Pytest и думаю, не помогут ли приборы, но я не совсем понимаю их.И я предполагаю, что есть более питонический способ сделать это с помощью unittest.Кажется, мне нужен метод, которому я могу передать различные аргументы dict, но я не могу понять, как это сделать.

from fly_app import app
import unittest

class FlaskTestCase(unittest.TestCase):

    def test_city_code(self):
        tester = app.test_client(self)
        response = tester.post('/flight_search/extensive', data=dict(origin="xxxx"))
        self.assertIn(b'That does not appear to be a valid city code', response.data)

    def test_code_pairs(self):
        tester = app.test_client(self)
        response = tester.post('/flight_search/extensive', data=dict(origin="HFD", destination="CAS"))
        self.assertIn(b'This origin-destination pair is not in searchable cache', response.data)

    def test_duration_range(self):
        tester = app.test_client(self)
        response = tester.post('/flight_search/extensive', data=dict(origin="MSP", destination="NYC", min_duration=20))
        self.assertIn(b'Number must be between 1 and 15', response.data)

    def test_duration_integer(self):
        tester = app.test_client(self)
        response = tester.post('/flight_search/extensive', data=dict(origin="MSP", destination="NYC", min_duration='abc'))
        self.assertIn(b'Not a valid integer value', response.data)

    def test_duration_pair(self):
        tester = app.test_client(self)
        response = tester.post('/flight_search/extensive', data=dict(origin="MSP", destination="NYC", min_duration=10, max_duration=7))
        self.assertIn(b'Maximum trip length cannot be less than minimum', response.data)

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

1 Ответ

0 голосов
/ 27 октября 2018

Я предлагаю вам создать собственный метод asserter (assertExtensiveFlightSearchGivesError(self, data, expected_error_message)), чтобы удалить некоторые дубликаты:

class FlaskTestCase(unittest.TestCase):
    def assertExtensiveFlightSearchGivesError(self, data, expected_error_message):
        response = test_client.post("/flight_search/extensive", data=data)
        self.assertEqual(4xx, response.status_code)
        self.assertIn(expected_error_message, response.data, "extensive flight search did not contain expected error message")

    def test_city_code(self):
        self.assertExtensiveFlightSearchGivesError(
            {'origin': 'xxx'},
            b'That does not appear to be a valid city code'
        )

    def test_code_pairs(self):
        self.assertExtensiveFlightSearchGivesError(
            {'origin': "HFD", 'destination': "CAS"},
            b'This origin-destination pair is not in searchable cache'
        )

    # ... and so on

Вы также можете собрать все тестовые примеры вместе и использовать .subTest():

TEST_CASES = [
    ({'origin': 'xxx'}, b'That does not appear to be a valid city code'),
    ({'origin': "HFD", 'destination': "CAS"}, b'This origin-destination pair is not in searchable cache')
]

class FlaskTestCase2(unittest.TestCase):
    def assertExtensiveFlightSearchGivesError(self, data, expected_error_message):
        response = test_client.post("/flight_search/extensive", data=data)
        self.assertEqual(4xx, response.status_code)
        self.assertIn(expected_error_message, response.data, "extensive flight search did not contain expected error message")

    def test_all_error_cases(self):
        for data, expected_error_message in TEST_CASES:
            with self.subTest():
                self.assertExtensiveFlightSearchGivesError(data, expected_error_message)

Но в вашем случае самый лучший пример кода IMO яснее.

...