I want to try to write some code following TDD practice. I want to create simple app based on python's tornado framework. I was looking through the internet how people write tests for tornado and found something like this:
class TestSomeHandler(AsyncHTTPTestCase):
def test_success(self):
response = self.fetch('/something')
self.assertEqual(response.code, 200)
Correct me if I'm wrong but it looks more like integration tests. Instead of it I'm trying to write simple unit test for some dummy handler. For example such one:
class SomeHandler(BaseHandler):
@gen.coroutine
def get(self):
try:
from_date = self.get_query_argument("from", default=None)
datetime.datetime.strptime(from_date, '%Y-%m-%d')
except ValueError:
raise ValueError("Incorrect argument value for from_date = %s, should be YYYY-MM-DD" % from_date)
And test would look like:
class TestSomeHandler(AsyncHTTPTestCase):
def test_no_from_date_param(self):
handler = SomeHandler()
with self.assertRaises(ValueError):
handler.get()
I know I miss at get()
application and request. Not handled yet how to create them.
But my question is, do people write tests for tornado like in first example or somebody calls handlers inside of app? What pattern to follow? It would be nice if somebody have relevant code to share.
The pattern with AsyncHTTPTestCase
is used mostly because, it makes all the request stuff for you. Of course one can also use AsyncTestCase
and handle it manually.
AsyncTestCase example. Since it will be testing get
method that is coroutine, we will use gen_test
to make it a bit simpler. RequestHandler
requires Application
and HTTPRequest
objects. Because we are not relaying of app's settings, ui_methods, etc. Application
is a simple mock.
from tornado.testing import AsyncTestCase, gen_test
from tornado.web import Application
from tornado.httpserver import HTTPRequest
from unittest.mock import Mock
class TestSomeHandler(AsyncTestCase):
@gen_test
def test_no_from_date_param(self):
mock_application = Mock(spec=Application)
payload_request = HTTPRequest(
method='GET', uri='/test', headers=None, body=None
)
handler = SomeHandler(mock_application, payload_request)
with self.assertRaises(ValueError):
yield handler.get()
IMHO it is up to you which pattern to use. I choose AsyncHTTPTestCase
for http-verb methods (get, post and so on), because:
Of course rest of handler's methods tested with AsyncTestCase
.