Fixed #3162 -- Added coded to catch and rethrow exceptions that are thrown by the views visited by the test client. Thanks, Ben <afternoon@uk2.net>.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@4482 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
23272de5db
commit
f9cdde0cb4
1
AUTHORS
1
AUTHORS
|
@ -53,6 +53,7 @@ answer newbie questions, and generally made Django that much better:
|
||||||
Shannon -jj Behrens <http://jjinux.blogspot.com/>
|
Shannon -jj Behrens <http://jjinux.blogspot.com/>
|
||||||
Esdras Beleza <linux@esdrasbeleza.com>
|
Esdras Beleza <linux@esdrasbeleza.com>
|
||||||
James Bennett
|
James Bennett
|
||||||
|
Ben <afternoon@uk2.net>
|
||||||
Paul Bissex <http://e-scribe.com/>
|
Paul Bissex <http://e-scribe.com/>
|
||||||
Simon Blanchard
|
Simon Blanchard
|
||||||
Andrew Brehaut <http://brehaut.net/blog>
|
Andrew Brehaut <http://brehaut.net/blog>
|
||||||
|
|
|
@ -4,6 +4,7 @@ from django.contrib.sites.models import Site
|
||||||
from django.template import Context, loader
|
from django.template import Context, loader
|
||||||
from django.core import validators
|
from django.core import validators
|
||||||
from django import oldforms
|
from django import oldforms
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
class UserCreationForm(oldforms.Manipulator):
|
class UserCreationForm(oldforms.Manipulator):
|
||||||
"A form that creates a user, with no privileges, from the given username and password."
|
"A form that creates a user, with no privileges, from the given username and password."
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
import sys
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.handlers.base import BaseHandler
|
from django.core.handlers.base import BaseHandler
|
||||||
from django.core.handlers.wsgi import WSGIRequest
|
from django.core.handlers.wsgi import WSGIRequest
|
||||||
|
from django.core.signals import got_request_exception
|
||||||
from django.dispatch import dispatcher
|
from django.dispatch import dispatcher
|
||||||
from django.http import urlencode, SimpleCookie
|
from django.http import urlencode, SimpleCookie
|
||||||
from django.test import signals
|
from django.test import signals
|
||||||
|
@ -100,6 +102,14 @@ class Client:
|
||||||
self.defaults = defaults
|
self.defaults = defaults
|
||||||
self.cookies = SimpleCookie()
|
self.cookies = SimpleCookie()
|
||||||
self.session = {}
|
self.session = {}
|
||||||
|
self.exc_info = None
|
||||||
|
|
||||||
|
def store_exc_info(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Utility method that can be used to store exceptions when they are
|
||||||
|
generated by a view.
|
||||||
|
"""
|
||||||
|
self.exc_info = sys.exc_info()
|
||||||
|
|
||||||
def request(self, **request):
|
def request(self, **request):
|
||||||
"""
|
"""
|
||||||
|
@ -128,6 +138,9 @@ class Client:
|
||||||
on_template_render = curry(store_rendered_templates, data)
|
on_template_render = curry(store_rendered_templates, data)
|
||||||
dispatcher.connect(on_template_render, signal=signals.template_rendered)
|
dispatcher.connect(on_template_render, signal=signals.template_rendered)
|
||||||
|
|
||||||
|
# Capture exceptions created by the handler
|
||||||
|
dispatcher.connect(self.store_exc_info, signal=got_request_exception)
|
||||||
|
|
||||||
response = self.handler(environ)
|
response = self.handler(environ)
|
||||||
|
|
||||||
# Add any rendered template detail to the response
|
# Add any rendered template detail to the response
|
||||||
|
@ -142,6 +155,11 @@ class Client:
|
||||||
else:
|
else:
|
||||||
setattr(response, detail, None)
|
setattr(response, detail, None)
|
||||||
|
|
||||||
|
# Look for a signalled exception and reraise it
|
||||||
|
if self.exc_info:
|
||||||
|
raise self.exc_info[1], None, self.exc_info[2]
|
||||||
|
|
||||||
|
# Update persistent cookie and session data
|
||||||
if response.cookies:
|
if response.cookies:
|
||||||
self.cookies.update(response.cookies)
|
self.cookies.update(response.cookies)
|
||||||
|
|
||||||
|
|
|
@ -291,6 +291,17 @@ for testing purposes:
|
||||||
|
|
||||||
.. _RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
.. _RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||||
|
|
||||||
|
Exceptions
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
If you point the Test Client at a view that raises an exception, that exception
|
||||||
|
will be visible in the test case. You can then use a standard ``try...catch``
|
||||||
|
block, or ``unittest.TestCase.assertRaises()`` to test for exceptions.
|
||||||
|
|
||||||
|
The only exceptions that are not visible in a Test Case are ``Http404``,
|
||||||
|
``PermissionDenied`` and ``SystemExit``. Django catches these exceptions
|
||||||
|
internally and converts them into the appropriate HTTP responses codes.
|
||||||
|
|
||||||
Persistent state
|
Persistent state
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -114,4 +114,14 @@ class ClientTest(unittest.TestCase):
|
||||||
|
|
||||||
# Check that the session was modified
|
# Check that the session was modified
|
||||||
self.assertEquals(self.client.session['tobacconist'], 'hovercraft')
|
self.assertEquals(self.client.session['tobacconist'], 'hovercraft')
|
||||||
|
|
||||||
|
def test_view_with_exception(self):
|
||||||
|
"Request a page that is known to throw an error"
|
||||||
|
self.assertRaises(KeyError, self.client.get, "/test_client/broken_view/")
|
||||||
|
|
||||||
|
#Try the same assertion, a different way
|
||||||
|
try:
|
||||||
|
self.client.get('/test_client/broken_view/')
|
||||||
|
self.fail('Should raise an error')
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
|
@ -6,5 +6,6 @@ urlpatterns = patterns('',
|
||||||
(r'^post_view/$', views.post_view),
|
(r'^post_view/$', views.post_view),
|
||||||
(r'^redirect_view/$', views.redirect_view),
|
(r'^redirect_view/$', views.redirect_view),
|
||||||
(r'^login_protected_view/$', views.login_protected_view),
|
(r'^login_protected_view/$', views.login_protected_view),
|
||||||
(r'^session_view/$', views.session_view)
|
(r'^session_view/$', views.session_view),
|
||||||
|
(r'^broken_view/$', views.broken_view)
|
||||||
)
|
)
|
||||||
|
|
|
@ -36,11 +36,13 @@ login_protected_view = login_required(login_protected_view)
|
||||||
|
|
||||||
def session_view(request):
|
def session_view(request):
|
||||||
"A view that modifies the session"
|
"A view that modifies the session"
|
||||||
|
|
||||||
request.session['tobacconist'] = 'hovercraft'
|
request.session['tobacconist'] = 'hovercraft'
|
||||||
|
|
||||||
t = Template('This is a view that modifies the session.',
|
t = Template('This is a view that modifies the session.',
|
||||||
name='Session Modifying View Template')
|
name='Session Modifying View Template')
|
||||||
c = Context()
|
c = Context()
|
||||||
return HttpResponse(t.render(c))
|
return HttpResponse(t.render(c))
|
||||||
|
|
||||||
|
def broken_view(request):
|
||||||
|
"""A view which just raises an exception, simulating a broken view."""
|
||||||
|
raise KeyError("Oops! Looks like you wrote some bad code.")
|
||||||
|
|
Loading…
Reference in New Issue