Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

This project contains extensions to test Tornado apps under pyvows.

branch: master

Fetching latest commit…

Octocat-spinner-32-eaf2f5

Cannot retrieve the latest commit at this time

Octocat-spinner-32 tornado_pyvows
Octocat-spinner-32 vows
Octocat-spinner-32 .gitignore
Octocat-spinner-32 .travis.yml
Octocat-spinner-32 Makefile
Octocat-spinner-32 README.mkd
Octocat-spinner-32 requirements.txt
Octocat-spinner-32 setup.py
README.mkd

Build
Status

Tornado_pyVows

This project contains extensions to test Tornado apps under pyVows.

TornadoHTTPContext

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):
        self.write("hello_world")

    def post(self):
        self.write("hello_world")


@Vows.batch
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):
            expect(topic).to_equal("hello_world")

    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

IsolatedTornadoHTTPContext

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

@Vows.batch
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):
            expect(topic).Not.to_be_an_error()

        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):
            expect(topic).Not.to_be_an_error()

        def shouldReturnTheExpectedTopic(self, resp):
            expect(resp.body).to_equal('echo')

TornadoContext

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")

@Vows.batch
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.

@Vows.batch
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()
            http_client.fetch("http://heynemann.github.com/pyvows/",
                              self.stop)
            return self.wait()

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

Contributors

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

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

Something went wrong with that request. Please try again.