pax_global_header00006660000000000000000000000064126002561170014512gustar00rootroot0000000000000052 comment=875cddd281a13d58c2b7acd5e3b79ee5bf32249a tornado_pyvows-0.6.1/000077500000000000000000000000001260025611700146135ustar00rootroot00000000000000tornado_pyvows-0.6.1/.gitignore000066400000000000000000000001001260025611700165720ustar00rootroot00000000000000*.pyc *.swp build dist pyVows.egg-info tornado_pyvows.egg-info/ tornado_pyvows-0.6.1/.travis.yml000066400000000000000000000002561260025611700167270ustar00rootroot00000000000000language: python python: - "2.6" - "2.7" before_install: sudo apt-get install -y libevent-dev python-gevent python-lxml install: make setup script: make test tornado_pyvows-0.6.1/Makefile000066400000000000000000000001121260025611700162450ustar00rootroot00000000000000 test: @env PYTHONPATH=. pyvows vows/ setup: @pip install -Ue.\[test\] tornado_pyvows-0.6.1/README.mkd000066400000000000000000000122761260025611700162550ustar00rootroot00000000000000[![Build Status](https://secure.travis-ci.org/rosner/tornado_pyvows.png?branch=master)](http://travis-ci.org/rosner/tornado_pyvows) 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: ```python 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](https://github.com/rafaelcaricio/tornado_pyvows/blob/master/vows/client_vows.py) IsolatedTornadoHTTPContext -------------------------- The new `IsolatedTornadoHTTPContext` creates a new `HTTPServer` that runs the application. This helps when testing handlers using mocks, e.g.:: ```python @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`: ```python 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. ```python @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): - Rafael CarĂ­cio [@rafaelcaricio](https://github.com/rafaelcaricio) - Bernardo Heynemann [@heynemann](https://github.com/heynemann) - Daniel Truemper [@truemped](https://github.com/truemped) - Norman Rosner [@rosner](https://github.com/rosner) tornado_pyvows-0.6.1/requirements.txt000066400000000000000000000000431260025611700200740ustar00rootroot00000000000000pyvows tornado pycurl urllib3 mock tornado_pyvows-0.6.1/setup.py000066400000000000000000000036201260025611700163260ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- # tornado-pyvows extensions # https://github.com/rafaelcaricio/tornado-pyvows # Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 globo.com rafael@caricio.com import os from setuptools import setup from imp import load_source version = load_source('version', os.path.join("tornado_pyvows", "version.py")) tests_require = ['mock'] setup( name = 'tornado_pyvows', version = '.'.join([str(item) for item in version.__version__]), description = "tornado_pyvows are pyvows extensions to tornado web framework.", long_description = """ tornado_pyvows are pyvows extensions to tornado web framework. """, keywords = 'testing vows test tdd', author = u'Rafael Caricio', author_email = 'rafael@caricio.com', #Contributors #contributor = 'Bernardo Heynemann', #contributor_email = 'heynemann@gmail.com', #contributor = 'Daniel Truemper', #contributor_email = 'truemped@googlemail.com', #contributor = 'Norman Rosner', #contributor_email = 'norman@rosner.io', url = 'https://github.com/rafaelcaricio/tornado_pyvows', license = 'MIT', classifiers = ['Development Status :: 3 - Alpha', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Natural Language :: English', 'Operating System :: MacOS', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python :: 2.6', 'Topic :: Software Development :: Testing' ], packages = ['tornado_pyvows'], package_dir = {"tornado_pyvows": "tornado_pyvows"}, tests_require = tests_require, extras_require = { 'test': tests_require, }, install_requires=[ "pyvows", "tornado", "pycurl", "urllib3" ], ) tornado_pyvows-0.6.1/tornado_pyvows/000077500000000000000000000000001260025611700177105ustar00rootroot00000000000000tornado_pyvows-0.6.1/tornado_pyvows/__init__.py000066400000000000000000000005641260025611700220260ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- # tornado-pyvows extensions # https://github.com/rafaelcaricio/tornado-pyvows # Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 globo.com rafael@caricio.com # flake8: noqa from .context import ( TornadoContext, TornadoHTTPContext, IsolatedTornadoHTTPContext ) tornado_pyvows-0.6.1/tornado_pyvows/context.py000066400000000000000000000176371260025611700217640ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- # tornado-pyvows extensions # https://github.com/rafaelcaricio/tornado-pyvows # Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 Rafael Caricio rafael@caricio.com import sys import time import contextlib import urllib import tornado.ioloop from tornado.httpclient import AsyncHTTPClient from tornado.httpserver import HTTPServer from tornado.stack_context import NullContext from tornado.testing import get_unused_port from tornado.web import Application, URLSpec from pyvows import Vows from urllib3.filepost import encode_multipart_formdata class AsyncTestCase(object): def get_new_ioloop(self): return tornado.ioloop.IOLoop.instance() @contextlib.contextmanager def stack_context(self): try: yield except: self.failure = sys.exc_info() self.stop() def stop(self, _arg=None, **kwargs): assert _arg is None or not kwargs self.stop_args = kwargs or _arg if self.running: self.io_loop.stop() self.running = False self.stopped = True def wait(self, condition=None, timeout=5): if not self.stopped: if timeout: def timeout_func(): try: raise AssertionError( 'Async operation timed out after %d seconds' % timeout ) except: self.failure = sys.exc_info() self.stop() self.io_loop.add_timeout(time.time() + timeout, timeout_func) while True: self.running = True with NullContext(): self.io_loop.start() if (self.failure is not None or condition is None or condition()): break assert self.stopped self.stopped = False if self.failure is not None: raise self.failure[0], self.failure[1], self.failure[2] result = self.stop_args self.stop_args = None return result class AsyncHTTPTestCase(AsyncTestCase): def initialize_ioloop(self): self.io_loop = self.get_new_ioloop() self.http_client = AsyncHTTPClient(io_loop=self.io_loop) def setup(self): self.stopped = False self.running = False self.failure = None self.stop_args = None if 'get_app' in dir(self.__class__): self.initialize_ioloop() self.app = self.get_app() elif hasattr(self, 'get_handler_spec') and self.get_handler_spec: spec = self.get_handler_spec() if spec: if isinstance(spec, tuple): if len(spec) == 3: (pattern, handler, kwargs) = spec elif len(spec) == 2: (pattern, handler) = spec kwargs = {} elif isinstance(spec, URLSpec): pattern = spec.regex.pattern handler = spec.handler_class kwargs = spec.kwargs # create an isolated version of the handler self.isolated_handler = type('IsolatedHandler', (handler,), {}) self.initialize_ioloop() self.app = Application([ (pattern, self.isolated_handler, kwargs) ], self.get_application_settings()) if self.app: self.port = get_unused_port() self.http_server = HTTPServer( self.app, io_loop=self.io_loop, **self.get_httpserver_options() ) self.http_server.listen(self.port, address="0.0.0.0") def fetch(self, path, **kwargs): """ Simple wrapper around ``http_client``. If the given ``path`` doesn't start with 'http' than ``path`` is passed on to the ``http_client.fetch`` """ self.http_client.fetch(self.get_url(path), self.stop, **kwargs) return self.wait() def get_httpserver_options(self): return {} def get_url(self, path): if not path.startswith('http'): return 'http://localhost:%s%s' % (self.port, path) return path def teardown(self): if 'http_server' in dir(self.__class__): self.http_server.stop() if 'http_client' in dir(self.__class__): self.http_client.close() class ParentAttributeMixin(object): def get_parent_argument(self, name): parent = self.parent while parent: if hasattr(parent, name): return getattr(parent, name) parent = parent.parent return None def __getattribute__(self, name): try: return object.__getattribute__(self, name) except AttributeError: return self.get_parent_argument(name) class TornadoContext(Vows.Context, AsyncTestCase, ParentAttributeMixin): def __init__(self, parent, *args, **kwargs): Vows.Context.__init__(self, parent) ParentAttributeMixin.__init__(self) AsyncTestCase(*args, **kwargs) super(TornadoContext, self).ignore( 'get_parent_argument', 'get_app', 'fetch', 'get_httpserver_options', 'get_url', 'initialize_ioloop', 'get_new_ioloop', 'stack_context', 'stop', 'wait' ) class TornadoHTTPContext(Vows.Context, AsyncHTTPTestCase, ParentAttributeMixin): def __init__(self, parent, *args, **kwargs): Vows.Context.__init__(self, parent) ParentAttributeMixin.__init__(self) AsyncHTTPTestCase.__init__(self, *args, **kwargs) super(TornadoHTTPContext, self).ignore( 'get_parent_argument', 'get_app', 'fetch', 'get_httpserver_options', 'get_url', 'get_new_ioloop', 'stack_context', 'stop', 'wait', 'get', 'post', 'delete', 'head', 'put', 'get_handler_spec', 'get_application_settings', 'get_test_handler', 'initialize_ioloop' ) def setup(self): AsyncHTTPTestCase.setup(self) def teardown(self): AsyncHTTPTestCase.teardown(self) def get_handler_spec(self): return None def get_application_settings(self): return None def get_test_handler(self): return self.isolated_handler def get(self, path, **kwargs): return self.fetch(path, method="GET", **kwargs) def delete(self, path, **kwargs): return self.fetch(path, method="DELETE") def put(self, path, **kwargs): return self.fetch(path, method="PUT", **kwargs) def head(self, path, **kwargs): return self.fetch(path, method="HEAD", **kwargs) def post(self, path, data={}, multipart=False, **kwargs): """ Convenience wrapper for the ``http_client``. :param multipart: If True the given ``data`` is encoded "multipart/form-data" through ``urllib3`` If the value is a tuple of two elements, then the first element is treated as the filename of the form-data section. """ body = None headers = {} if multipart: body, content_type = encode_multipart_formdata(data) headers["Content-Type"] = content_type else: body = urllib.urlencode(data, doseq=True) if 'headers' in kwargs: kwargs['headers'].update(headers) return self.fetch( path, method="POST", body=body, headers=headers, **kwargs ) class IsolatedTornadoHTTPContext(TornadoHTTPContext): def get_handler_spec(self): return self.get_parent_argument('get_handler_spec')() def get_application_settings(self): return self.get_parent_argument('get_application_settings')() tornado_pyvows-0.6.1/tornado_pyvows/version.py000066400000000000000000000004351260025611700217510ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- # tornado-pyvows extensions # https://github.com/rafaelcaricio/tornado-pyvows # Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 Rafael Caricio rafael@caricio.com __version__ = (0, 6, 1) tornado_pyvows-0.6.1/vows/000077500000000000000000000000001260025611700156115ustar00rootroot00000000000000tornado_pyvows-0.6.1/vows/__init__.py000066400000000000000000000004051260025611700177210ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # tornado-pyvows extensions # https://github.com/rafaelcaricio/tornado-pyvows # Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 globo.com rafael@caricio.com tornado_pyvows-0.6.1/vows/basecontext_vows.py000066400000000000000000000014721260025611700215640ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # tornado-pyvows extensions # https://github.com/rafaelcaricio/tornado-pyvows # Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 Daniel Truemper truemped@googlemail.com from functools import partial from pyvows import Vows, expect from tornado_pyvows import TornadoContext def async_method(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(partial(async_method, self.stop)) return self.wait() def and_have_the_correct_result(self, topic): expect(topic).to_equal("Pseudo Async Result") tornado_pyvows-0.6.1/vows/client_vows.py000066400000000000000000000043261260025611700205240ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # tornado-pyvows extensions # https://github.com/rafaelcaricio/tornado-pyvows # Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 Rafael Caricio rafael@caricio.com import json from tornado_pyvows import TornadoHTTPContext from pyvows import Vows, expect REQUESTBIN_BASE_URL = 'http://requestb.in' @Vows.batch class Post(TornadoHTTPContext): def setup(self): self.initialize_ioloop() def topic(self): response = self.post('%s/api/v1/bins' % REQUESTBIN_BASE_URL) requestbin_id = json.loads(response.body)['name'] return (requestbin_id, response) def should_be_ok(self, topic): _, response = topic expect(response.code).to_equal(200) class Get(TornadoHTTPContext): def topic(self, post_response): requestbin_id, response = post_response get_response = self.get( '%s/%s' % (REQUESTBIN_BASE_URL, requestbin_id) ) return get_response def should_be_ok(self, topic): expect(topic.code).to_equal(200) class Delete(TornadoHTTPContext): def topic(self, post_response): requestbin_id, response = post_response delete_response = self.delete( '%s/%s' % (REQUESTBIN_BASE_URL, requestbin_id) ) return delete_response def should_be_ok(self, topic): expect(topic.code).to_equal(200) class Head(TornadoHTTPContext): def topic(self, post_response): requestbin_id, response = post_response head_response = self.head( '%s/%s' % (REQUESTBIN_BASE_URL, requestbin_id) ) return head_response def should_be_ok(self, topic): expect(topic.code).to_equal(200) class Put(TornadoHTTPContext): def topic(self, post_response): requestbin_id, response = post_response put_response = self.put( '%s/%s' % (REQUESTBIN_BASE_URL, requestbin_id), body='' ) return put_response def should_be_ok(self, topic): expect(topic.code).to_equal(200) tornado_pyvows-0.6.1/vows/context_vows.py000066400000000000000000000113251260025611700207270ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # tornado-pyvows extensions # https://github.com/rafaelcaricio/tornado-pyvows # Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 Rafael Caricio rafael@caricio.com import json import tornado.web from pyvows import Vows, expect from tornado_pyvows import TornadoHTTPContext from vows.test_app import MainPageHandler @Vows.batch class Application(TornadoHTTPContext): def get_app(self): application = tornado.web.Application([ (r"/", MainPageHandler), ]) return application class GoodRequest(TornadoHTTPContext): def topic(self): return (200, None, self.get('/')) def the_response_should_be_ok(self, topic): expected_code, _, response = topic expect(response.code).to_equal(expected_code) class HomeUrlBody(GoodRequest): def should_be_hello_world(self, topic): _, _, response = topic expect(response.body).to_equal('Hello, world') class WhaneHeadRequest(GoodRequest): def topic(self): return (204, None, self.head('/')) class WhenPostWithUrlEncodedFormData(GoodRequest): def topic(self): data = {'message':'Hello UrlEncoded Form'} return (200, data, self.post('/', data=data)) def the_response_should_be_the_input(self, topic): _, data, response = topic expect(response.body).to_equal(json.dumps(data)) class WhenPostWithMultipartFormData(WhenPostWithUrlEncodedFormData): def topic(self): data = {'message':'Hello Multipart Form'} return (200, data, self.post('/', data=data, multipart=True)) class WhenPostWithFileUpload(GoodRequest): def topic(self): data = {'upload': ('the_file_name', 'This is the file content!')} return (200, data, self.post('/', data=data, multipart=True)) def the_response_should_contain_upload(self, topic): _, _, response = topic body = json.loads(response.body) expect(body).to_include('upload') def the_response_should_contain_filename(self, topic): _, _, response = topic body = json.loads(response.body)['upload'] expect(body).to_include('filename') def the_filename_should_be_the_same(self, topic): _, _, response = topic body = json.loads(response.body)['upload'] expect(body['filename']).to_include('the_file_name') def the_file_should_have_the_same_content(self, topic): _, _, response = topic body = json.loads(response.body)['upload']['body'] expect(body).to_equal('This is the file content!') class WhenPostWithMultipleFiles(WhenPostWithFileUpload): def topic(self): data = {'upload': ('the_file_name', 'This is the file content!'), 'second_file': ('other_file_name', 'Different content') } return (200, data, self.post('/', data=data, multipart=True)) def the_response_should_contain_second_file(self, topic): _, _, response = topic body = json.loads(response.body) expect(body).to_include('second_file') def the_response_should_contain_filename(self, topic): _, _, response = topic body = json.loads(response.body)['second_file'] expect(body).to_include('filename') def the_second_filename_should_be_the_same(self, topic): _, _, response = topic body = json.loads(response.body)['second_file'] expect(body['filename']).to_include('other_file_name') def the_content_of_the_second_file_should_be_the_same(self, topic): _, _, response = topic body = json.loads(response.body)['second_file']['body'] expect(body).to_equal('Different content') class WhenPostWithFileUploadAndArguments(WhenPostWithFileUpload): def topic(self): data = {'upload': ('the_file_name', 'This is the file content!'), 'argument':'value' } return (200, data, self.post('/', data=data, multipart=True)) def the_response_should_contain_argument(self, topic): _, _, response = topic body = json.loads(response.body) expect(body).to_include('argument') def the_argument_should_have_value(self, topic): _, _, response = topic argument = json.loads(response.body)['argument'] expect(argument).to_equal('value') tornado_pyvows-0.6.1/vows/isolation_vows.py000066400000000000000000000076241260025611700212530ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- # tornado-pyvows extensions # https://github.com/rafaelcaricio/tornado-pyvows # Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 Rafael Caricio rafael@caricio.com from pyvows import Vows, expect from tornado_pyvows import TornadoHTTPContext, IsolatedTornadoHTTPContext from tornado import gen from tornado.web import RequestHandler, asynchronous from mock import CallableMixin, NonCallableMock class AsyncCallableMixin(CallableMixin): """Change the __call__ method such that it does not return but call the `callback` kwarg with the return value. """ def __call__(_mock_self, *args, **kwargs): cb = kwargs.get('callback', None) _mock_self._mock_check_sig(*args, **kwargs) if cb: del kwargs['callback'] result = _mock_self._mock_call(*args, **kwargs) cb(result) else: return _mock_self._mock_call(*args, **kwargs) class AsyncMock(AsyncCallableMixin, NonCallableMock): pass @Vows.assertion def has_been_called_with(mock, *args, **kwargs): mock.assert_called_with(*args, **kwargs) @Vows.assertion def has_been_called_once_with(mock, *args, **kwargs): mock.assert_called_once(*args, **kwargs) @Vows.assertion def has_any_call(mock, *args, **kwargs): mock.assert_any_call(*args, **kwargs) @Vows.assertion def has_calls(mock, calls, any_order=False): mock.assert_has_calls(calls, any_order=any_order) class ExampleHandler(RequestHandler): @asynchronous @gen.engine def get(self): echo = yield gen.Task(self.echo) self.finish(echo) def echo(self, callback=None): callback('echo') @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 ThatBlahsAgain(ThatBlahsBlahs): def topic(self, topic): yield (topic, self.fetch('/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') class ThatStillHasNoSideEffects(IsolatedTornadoHTTPContext): def topic(self): mock = AsyncMock() mock.return_value = 'another 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('another mocked echo') def theMockHasBeenCalledOnce(self, topic): (mock, _) = topic expect(mock).has_been_called_with() def thereAreNoMoreActionsOnTheMock(self, topic): (mock, _) = topic expect(mock.call_count).to_equal(1) tornado_pyvows-0.6.1/vows/readme_sample1_vows.py000066400000000000000000000026051260025611700221230ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # tornado-pyvows extensions # https://github.com/rafaelcaricio/tornado-pyvows # Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 Rafael Caricio rafael@caricio.com 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 tornado_pyvows-0.6.1/vows/test_app.py000066400000000000000000000014621260025611700200050ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # tornado-pyvows extensions # https://github.com/rafaelcaricio/tornado-pyvows # Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 globo.com rafael@caricio.com import json import tornado.web from tornado.web import RequestHandler class MainPageHandler(RequestHandler): def head(self): self.set_status(204) def get(self): self.write("Hello, world") def post(self): result = {} for arg, value in self.request.arguments.iteritems(): result[arg] = value.pop() for field_name, list_of_files in self.request.files.iteritems(): file_dict = list_of_files.pop() result[field_name] = file_dict self.write(json.dumps(result))