I have written a relatively simple web app using Flask and WTForms with standard and custom form validators. I am now trying to learn Python testing. I have written the following tests.py file that works fine with unittest, but has redundancy. Is there a better, more effecient, more pythonic (DNRY) way to do this? I've looked at some pytest tutorials and wonder if fixtures would help, but I cannot quite understand them. And I assume there is a more pythonic way to do this with unittest. It seems I need a method to which I can pass the different dict arguments, but I cannot figure out how to do that.
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()
I suggest you create a custom asserter method ( assertExtensiveFlightSearchGivesError(self, data, expected_error_message)
) to remove some of the duplication:
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
You could also collect all the test cases together and use .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)
But in your case, IMO the topmost code example is clearer.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.