Testing Tornado app for 4xx status code
Question: Consider the following Tornado (v 4.0.2) application, which is a little bit
modified version of official [hello
world](http://www.tornadoweb.org/en/latest/#hello-world) example:

    
    
    import tornado.ioloop
    import tornado.web
    
    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            self.set_status(400)
            self.write("Hello, world")
    
    application = tornado.web.Application([
        (r"/", MainHandler),
    ])
    
    if __name__ == "__main__":
        application.listen(8888)
        tornado.ioloop.IOLoop.instance().start()
    

As you can see, the only difference here is `set_status` call in
`MainHandler`. Now, I save this code into `app.py`, then I open `tests.py` and
I put there this simple unit test:

    
    
    import tornado.ioloop
    from tornado.httpclient import HTTPRequest
    from tornado.testing import AsyncHTTPTestCase, gen_test
    
    from app import application
    
    class SimpleTest(AsyncHTTPTestCase):
        def get_app(self):
            return application
    
        def get_new_ioloop(self):
            return tornado.ioloop.IOLoop.instance()
    
        @gen_test
        def test_bad_request(self):
            request = HTTPRequest(url=self.get_url('/'))
            response = yield self.http_client.fetch(request)
            self.assertEqual(response.code, 400)
    

When I run this test with `python -m tornado.test.runtests tests` I get the
following result:

    
    
    E
    ======================================================================
    ERROR: test_bad_request (tests.SimpleTest)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/usr/local/lib/python2.7/dist-packages/tornado/testing.py", line 118, in __call__
        result = self.orig_method(*args, **kwargs)
      File "/usr/local/lib/python2.7/dist-packages/tornado/testing.py", line 494, in post_coroutine
        timeout=timeout)
      File "/usr/local/lib/python2.7/dist-packages/tornado/ioloop.py", line 418, in run_sync
        return future_cell[0].result()
      File "/usr/local/lib/python2.7/dist-packages/tornado/concurrent.py", line 109, in result
        raise_exc_info(self._exc_info)
      File "/usr/local/lib/python2.7/dist-packages/tornado/gen.py", line 631, in run
        yielded = self.gen.throw(*sys.exc_info())
      File "tests.py", line 18, in test_bad_request
        response = yield self.http_client.fetch(request)
      File "/usr/local/lib/python2.7/dist-packages/tornado/gen.py", line 628, in run
        value = future.result()
      File "/usr/local/lib/python2.7/dist-packages/tornado/concurrent.py", line 111, in result
        raise self._exception
    HTTPError: HTTP 400: Bad Request
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.022s
    
    FAILED (errors=1)
    [E 140929 12:55:59 testing:687] FAIL
    

Obviously this is correct, because the handler sets 400 status code. **But how
can I test my application for such case?** I think 4xx codes are useful, so I
don't want to give them up. However I'm new to Tornado and I wasn't able to
find a way to test them. Is there any?


Answer: Try this:

    
    
        @gen_test
        def test_bad_request(self):
            request = HTTPRequest(url=self.get_url('/'))
            with self.assertRaises(tornado.httpclient.HTTPError) as context:
                yield self.http_client.fetch(request)
    
            self.assertEqual(context.exception.code, 400)
    

See the documentation for
[assertRaises](https://docs.python.org/2/library/unittest.html#unittest.TestCase.assertRaises).

