tornadoweb / tornadoweb/tornado
AsyncHTTPTestCase's fetch swallows httpclient exception
Open
Nobody has claimed this yet.
testing
- Dominant language
- Python
- Stars
- 22.2k
- Forks
- 5.6k
- Avg merge
- 3h 42m
- Merged PRs (30d)
- 16
Description
Python: 3.5.1
Tornado: 4.3
Ubuntu 12.04
Case:
import unittest
from tornado import testing
from tornado import web
from tornado import gen
class Handler(web.RequestHandler):
@gen.coroutine
def post(self):
self.write('spam')
class HandlerTest(testing.AsyncHTTPTestCase):
def get_app(self):
return web.Application([('/', Handler)])
def test_post(self):
response = self.fetch('/', method='POST')
self.assertEqual(b'spam', response.body)
if __name__ == '__main__':
unittest.main()
Produces:
F
======================================================================
FAIL: test_post (__main__.HandlerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/t35/lib/python3.5/site-packages/tornado/testing.py", line 132, in __call__
result = self.orig_method(*args, **kwargs)
File "test.py", line 20, in test_post
self.assertEqual(b'spam', response.body)
AssertionError: b'spam' != None
----------------------------------------------------------------------
Ran 1 test in 0.005s
FAILED (failures=1)
instead of "meaningful" error.
If changed to @gen_test, it produce proper error:
import unittest
from tornado import testing
from tornado import web
from tornado import gen
from tornado.testing import gen_test
class Handler(web.RequestHandler):
@gen.coroutine
def post(self):
self.write('spam')
class HandlerTest(testing.AsyncHTTPTestCase):
def get_app(self):
return web.Application([('/', Handler)])
@gen_test
def test_post(self):
response = self.http_client.fetch(self.get_url('/'), method='POST')
self.assertEqual(b'spam', response.body)
if __name__ == '__main__':
unittest.main()
and the error, that is ok:
E
======================================================================
ERROR: test_post (__main__.HandlerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/t35/lib/python3.5/site-packages/tornado/testing.py", line 132, in __call__
result = self.orig_method(*args, **kwargs)
File "/tmp/t35/lib/python3.5/site-packages/tornado/testing.py", line 525, in post_coroutine
timeout=timeout)
File "/tmp/t35/lib/python3.5/site-packages/tornado/ioloop.py", line 453, in run_sync
return future_cell[0].result()
File "/tmp/t35/lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "<string>", line 3, in raise_exc_info
File "/tmp/t35/lib/python3.5/site-packages/tornado/gen.py", line 267, in wrapper
result = func(*args, **kwargs)
File "/tmp/t35/lib/python3.5/types.py", line 243, in wrapped
coro = func(*args, **kwargs)
File "/tmp/t35/lib/python3.5/site-packages/tornado/testing.py", line 508, in pre_coroutine
result = f(self, *args, **kwargs)
File "test.py", line 22, in test_post
self.assertEqual(b'spam', response.body)
AttributeError: 'Future' object has no attribute 'body'
----------------------------------------------------------------------
Ran 1 test in 0.006s
FAILED (errors=1)
ERROR:tornado.application:Future <tornado.concurrent.Future object at 0x7ffb966965c0> exception was never retrieved: Traceback (most recent call last):
File "/tmp/t35/lib/python3.5/site-packages/tornado/stack_context.py", line 314, in wrapped
ret = fn(*args, **kwargs)
File "/tmp/t35/lib/python3.5/site-packages/tornado/gen.py", line 264, in <lambda>
future, lambda future: callback(future.result()))
File "/tmp/t35/lib/python3.5/site-packages/tornado/simple_httpclient.py", line 353, in _on_connect
('not ' if body_expected else '', self.request.method))
ValueError: Body must not be None for method POST (unless allow_nonstandard_methods is true)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the shown test_post case, then inspect AsyncHTTPTestCase.fetch in tornado/testing.py and the exception path in tornado/simple_httpclient.py. Add regression coverage for this failure and verify that fetch surfaces the underlying HTTP-client error instead of returning a response with body set to None.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- testing
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100