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