.. _guide.testing: Unit testing ============ Thanks to `WebOb`_, webapp2 is very testable. Testing a handler is a matter of building a custom ``Request`` object and calling ``get_response()`` on it passing the WSGI application. Let's see an example. First define a simple 'Hello world' handler to be tested:: import webapp2 class HelloHandler(webapp2.RequestHandler): def get(self): self.response.write('Hello, world!') app = webapp2.WSGIApplication([('/', HelloHandler)]) def main(): app.run() if __name__ == '__main__': main() To test if this handler returns the correct ``'Hello, world!'`` response, we build a request object using ``Request.blank()`` and call ``get_response()`` on it:: import unittest import webapp2 # from the app main.py import main class TestHandlers(unittest.TestCase): def test_hello(self): # Build a request object passing the URI path to be tested. # You can also pass headers, query arguments etc. request = webapp2.Request.blank('/') # Get a response for that request. response = request.get_response(main.app) # Let's check if the response is correct. self.assertEqual(response.status_int, 200) self.assertEqual(response.body, 'Hello, world!') To test different HTTP methods, just change the request object:: request = webapp2.Request.blank('/') request.method = 'POST' response = request.get_response(main.app) # Our handler doesn't implement post(), so this response will have a # status code 405. self.assertEqual(response.status_int, 405) Request.blank() --------------- ``Request.blank(path, environ=None, base_url=None, headers=None, POST=None, **kwargs)`` is a class method that creates a new request object for testing purposes. It receives the following parameters: path A URI path, urlencoded. The path will become path_info, with any query string split off and used. environ An environ dictionary. base_url If defined, wsgi.url_scheme, HTTP_HOST and SCRIPT_NAME will be filled in from this value. headers A list of ``(header_name, value)`` tuples for the request headers. POST A dictionary of POST data to be encoded, or a urlencoded string. This is a shortcut to set POST data in the environ. When set, the HTTP method is set to 'POST' and the CONTENT_TYPE is set to 'application/x-www-form-urlencoded'. kwargs Extra keyword arguments to be passed to ``Request.__init__()``. All necessary keys will be added to the environ, but the values you pass in will take precedence. app.get_response() ------------------ We can also get a response directly from the WSGI application, calling ``app.get_response()``. This is a convenience to test the app. It receives the same parameters as ``Request.blank()`` to build a request and call the application, returning the resulting response:: class HelloHandler(webapp2.RequestHandler): def get(self): self.response.write('Hello, world!') app = webapp2.WSGIApplication([('/', HelloHandler)]) # Test the app, passing parameters to build a request. response = app.get_response('/') assert response.status_int == 200 assert response.body == 'Hello, world!' Testing handlers could not be easier. Check the `WebOb`_ documentation for more information about the request and response objects. Testing App Engine services --------------------------- If you're using App Engine and need to test an application that uses Datastore, Memcache or other App Engine services, read `Local Unit Testing for Python `_ in the official documentation. The App Engine SDK provides the module ``google.appengine.ext.testbed`` that can be used to setup all the necessary service stubs for testing. .. _WebOb: http://docs.webob.org/