🚨 This project contains extensions to test Tornado apps with pyvows.
Python Makefile
Latest commit de8cd39 Jul 22, 2016 @rafaelcaricio committed on GitHub Merge pull request #22 from rafaelcaricio/update-readme
Updating contributors.
Failed to load latest commit information.
.gitignore First release Apr 30, 2011
Makefile Pyvows 2.0.5 has broken tornado_pyvows May 19, 2014
README.mkd Updating contributors. Jul 22, 2016
requirements.txt Add mock to requirements.txt Mar 19, 2013
setup.py Fixing for tornado 4 Mar 31, 2015




This project contains extensions to test Tornado apps under pyVows.


To test a tornado app (or handlers) use this context instead of the regular Vows.Context, like this:

import tornado
from tornado_pyvows import TornadoHTTPContext
from pyvows import Vows, expect

class HomeHandler(tornado.web.RequestHandler):

    def get(self):

    def post(self):

class SomeVows(TornadoHTTPContext):

    def get_app(self):
        application = tornado.web.Application([
            (r"/", HomeHandler),
        return application

    class HomeUrl(TornadoHTTPContext):
        def topic(self):
            self.http_client.fetch(self.get_url('/'), self.stop)
            response = self.wait()
            return response.body

        def should_be_hello_world(self, topic):

    class SameUrl(HomeUrl):
        def topic(self):
            For convenience you can also use ``get`` and ``post`` to wrap the 
            calls to the ``http_client``.
            response = self.get("/")
            return response.body

    class SimplePost(HomeUrl):
        def topic(self):
            response = self.post("/")
            return response.body

Each TornadoHTTPContext provides Tornado's testing methods like http_client, get_url, stop, wait, fetch and others.

If you're developing based on Tornados HTTPClient you can just do that with simple wrappers as seen in client_vows.py


The new IsolatedTornadoHTTPContext creates a new HTTPServer that runs the application. This helps when testing handlers using mocks, e.g.::

class ASimpleTestWithAMock(TornadoHTTPContext):

    def get_handler_spec(self):
        return (r'^/echo$', ExampleHandler)

    def get_application_settings(self):
        return {'debug': True}

    class AndASimpleTestCase(IsolatedTornadoHTTPContext):

        def topic(self):
            mock = AsyncMock()
            mock.return_value = 'mocked echo'
            self.get_test_handler().echo = mock

            yield (mock, self.fetch('/echo'))

        def shouldWorkAsUsual(self, topic):

        def shouldReturnTheExpectedTopic(self, topic):
            (_, resp) = topic
            expect(resp.body).to_equal('mocked echo')

        class ThatBlahsBlahs(TornadoHTTPContext):

            def topic(self, topic):
                yield (topic, self.fetch('/echo'))

            def shouldReturnTheExpectedTopic(self, topic):
                (_, resp) = topic
                expect(resp.body).to_equal('mocked echo')

    class ThatHasNoSideEffects(IsolatedTornadoHTTPContext):

        def topic(self):
            yield self.fetch('/echo')

        def shouldWorkAsUsual(self, topic):

        def shouldReturnTheExpectedTopic(self, resp):


If you want to test a tornado based app without the HTTP overhead you may also use the TornadoContext:

def asyncMethod(callback):
    callback("Pseudo Async Result")

class AsyncVows(TornadoContext):

    class CallbacksShouldWork(TornadoContext):

        def topic(self):
            self.io_loop = self.get_new_ioloop()
            self.io_loop.add_callback(lambda: asyncMethod(self.stop))
            return self.wait()

        def and_have_the_correct_result(self, topic):
            expect(topic).to_equal("Pseudo Async Result")

The above example creates a new IOLoop for every test, which is nice. Some libraries add callbacks to the IOLoop.instance() singleton, such as tornado.httpclient.AsyncHTTPClient. These libraries can be tested by overloading the get_new_ioloop method to return the IOLoop.instance() singleton.

class AsyncVows(TornadoContext):

    class PyVowsSiteVows(TornadoContext):

        def get_new_ioloop(self):
            return IOLoop.instance()

        def topic(self):
            self.io_loop = self.get_new_ioloop()
            http_client = AsyncHTTPClient()
            return self.wait()

        def to_be_about_asynchronous_testing(self, topic):
            expect(topic.body).to_include('Asynchronous BDD for Python')


Contributions are very welcome. To contribute fork it and create a pull request.

The team behind Tornado_pyVows (in order of joining the project):