blob: ea206affde5b3d4e3f295a28ed3876be129f0026 [file] [log] [blame]
.. _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 <http://code.google.com/appengine/docs/python/tools/localunittesting.html>`_
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/