File: README.mkd

package info (click to toggle)
tornado-pyvows 0.6.1-1~bpo8+1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-backports
  • size: 128 kB
  • sloc: python: 522; makefile: 8
file content (186 lines) | stat: -rw-r--r-- 5,310 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
[![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)