1.. _guide.testing:
2
3Unit testing
4============
5Thanks to `WebOb`_, webapp2 is very testable. Testing a handler is a matter
6of building a custom ``Request`` object and calling ``get_response()`` on it
7passing the WSGI application.
8
9Let's see an example. First define a simple 'Hello world' handler to be
10tested::
11
12    import webapp2
13
14    class HelloHandler(webapp2.RequestHandler):
15        def get(self):
16            self.response.write('Hello, world!')
17
18    app = webapp2.WSGIapplication([('/', HelloHandler)])
19
20    def main():
21        app.run()
22
23    if __name__ == '__main__':
24        main()
25
26To test if this handler returns the correct ``'Hello, world!'`` response, we
27build a request object using ``Request.blank()`` and call ``get_response()``
28on it::
29
30    import unittest
31    import webapp2
32
33    # from the app main.py
34    import main
35
36    class TestHandlers(unittest.TestCase):
37       def test_hello(self):
38           # Build a request object passing the URI path to be tested.
39           # You can also pass headers, query arguments etc.
40           request = webapp2.Request.blank('/')
41           # Get a response for that request.
42           response = request.get_response(main.app)
43
44           # Let's check if the response is correct.
45           self.assertEqual(response.status_int, 200)
46           self.assertEqual(response.body, 'Hello, world!')
47
48To test different HTTP methods, just change the request object::
49
50    request = webapp2.Request.blank('/')
51    request.method = 'POST'
52    response = request.get_response(main.app)
53
54    # Our handler doesn't implement post(), so this response will have a
55    # status code 405.
56    self.assertEqual(response.status_int, 405)
57
58
59Request.blank()
60---------------
61``Request.blank(path, environ=None, base_url=None, headers=None, POST=None, **kwargs)``
62is a class method that creates a new request object for testing purposes. It
63receives the following parameters:
64
65path
66  A URI path, urlencoded. The path will become path_info, with any query
67  string split off and used.
68environ
69  An environ dictionary.
70base_url
71  If defined, wsgi.url_scheme, HTTP_HOST and SCRIPT_NAME will be filled in
72  from this value.
73headers
74  A list of ``(header_name, value)`` tuples for the request headers.
75POST
76  A dictionary of POST data to be encoded, or a urlencoded string. This is a
77  shortcut to set POST data in the environ. When set, the HTTP method is set
78  to 'POST' and the CONTENT_TYPE is set to 'application/x-www-form-urlencoded'.
79kwargs
80  Extra keyword arguments to be passed to ``Request.__init__()``.
81
82All necessary keys will be added to the environ, but the values you pass in
83will take precedence.
84
85
86app.get_response()
87------------------
88We can also get a response directly from the WSGI application, calling
89``app.get_response()``. This is a convenience to test the app. It receives
90the same parameters as ``Request.blank()`` to build a request and call the
91application, returning the resulting response::
92
93    class HelloHandler(webapp2.RequestHandler):
94        def get(self):
95            self.response.write('Hello, world!')
96
97    app = webapp2.WSGIapplication([('/', HelloHandler)])
98
99    # Test the app, passing parameters to build a request.
100    response = app.get_response('/')
101    assert response.status_int == 200
102    assert response.body == 'Hello, world!'
103
104Testing handlers could not be easier. Check the `WebOb`_ documentation for more
105information about the request and response objects.
106
107
108Testing App Engine services
109---------------------------
110If you're using App Engine and need to test an application that uses Datastore,
111Memcache or other App Engine services, read
112`Local Unit Testing for Python <http://code.google.com/appengine/docs/python/tools/localunittesting.html>`_
113in the official documentation. The App Engine SDK provides the module
114``google.appengine.ext.testbed`` that can be used to setup all the necessary
115service stubs for testing.
116
117
118.. _WebOb: http://docs.webob.org/
119