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_url
The fixture above does a few simple things:
- Runs your application in a subprocess.
- Waits until the application starts (the
check_port
function). - Kills the application once the fixture is finalized.
- Returns
get_url
function, 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!