The following is a proof of concept for testing web applications written in Tornado with py.test.
Testing applications written in Tornado is a piece of cake. The package provides a bunch of handy tools for that, and in most cases that's all you need.
However, sometimes out-of-the-box tools are not enough. For instance, if you want to test a case where your handler responds with 4xx status code. Or if the aplication you're testing is using cookies. It is particularly uncomfortable to test such cases with tornado.testing.
Don't you think it would be great to accomplish this with a clean and elegant interface like requests?
Good news: it is possible with py.test and xprocess plugin. Just have a look at the code below:
@pytest.fixture(scope='session')
def test_server(xprocess, request):
def preparefunc(cwd):
def check_port():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
for i in xrange(10):
result = sock.connect_ex(('127.0.0.1', TEST_APP_PORT))
if result == 0:
return True
time.sleep(1)
return False
os.environ['APP_PORT'] = str(TEST_APP_PORT)
server_path = os.path.join(sys.prefix, 'bin', 'tornado_pytest_app.py')
return (check_port, [sys.executable, server_path])
pid, log = xprocess.ensure('tornado_pytest_app', preparefunc, restart=True)
def fin():
os.kill(pid, signal.SIGKILL)
request.addfinalizer(fin)
def get_url(url):
return 'http://localhost:%s%s' % (TEST_APP_PORT, url)
return get_urlThe fixture above does a few simple things:
- Runs your application in a subprocess.
- Waits until the application starts (the
check_portfunction). - Kills the application once the fixture is finalized.
- Returns
get_urlfunction, which you can use to get a URL for the test server.
Now you can write readable and elegant tests like the one below:
def test(test_server):
response = requests.get(test_server('/'))
assert response.status_code == 200
json = response.json()
assert 'status' in json
assert json['status'] == 'ok'The approach I'm proposing is not a replacement for unit tests. But it's probably the easiest way to write functional tests for your Tornado-based application. Have fun!