1 .. _guide.testing: 2 3 Unit testing 4 ============ 5 Thanks to `WebOb`_, webapp2 is very testable. Testing a handler is a matter 6 of building a custom ``Request`` object and calling ``get_response()`` on it 7 passing the WSGI application. 8 9 Let's see an example. First define a simple 'Hello world' handler to be 10 tested:: 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 26 To test if this handler returns the correct ``'Hello, world!'`` response, we 27 build a request object using ``Request.blank()`` and call ``get_response()`` 28 on 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 48 To 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 59 Request.blank() 60 --------------- 61 ``Request.blank(path, environ=None, base_url=None, headers=None, POST=None, **kwargs)`` 62 is a class method that creates a new request object for testing purposes. It 63 receives the following parameters: 64 65 path 66 A URI path, urlencoded. The path will become path_info, with any query 67 string split off and used. 68 environ 69 An environ dictionary. 70 base_url 71 If defined, wsgi.url_scheme, HTTP_HOST and SCRIPT_NAME will be filled in 72 from this value. 73 headers 74 A list of ``(header_name, value)`` tuples for the request headers. 75 POST 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'. 79 kwargs 80 Extra keyword arguments to be passed to ``Request.__init__()``. 81 82 All necessary keys will be added to the environ, but the values you pass in 83 will take precedence. 84 85 86 app.get_response() 87 ------------------ 88 We 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 90 the same parameters as ``Request.blank()`` to build a request and call the 91 application, 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 104 Testing handlers could not be easier. Check the `WebOb`_ documentation for more 105 information about the request and response objects. 106 107 108 Testing App Engine services 109 --------------------------- 110 If you're using App Engine and need to test an application that uses Datastore, 111 Memcache or other App Engine services, read 112 `Local Unit Testing for Python <http://code.google.com/appengine/docs/python/tools/localunittesting.html>`_ 113 in the official documentation. The App Engine SDK provides the module 114 ``google.appengine.ext.testbed`` that can be used to setup all the necessary 115 service stubs for testing. 116 117 118 .. _WebOb: http://docs.webob.org/ 119