Testing: making it easier to create mock Request objects

524 views
Skip to first unread message

Simon Willison

unread,
Aug 13, 2008, 7:48:50 AM8/13/08
to Django developers
(Not at all important for 1.0, but it's on my mind at the moment)

The django.test.Client test harness supports running tests against
view functions that have been hooked in to the URL conf. While this is
useful, I've stumbled across a number of cases where I've needed to
test a view function which isn't wired in to the URL conf.

I ended up writing some REALLY ugly code:

class MyTestCase(DjangoTestCase):
def extra_test_view(self, request):
...
return response

def setUp(self):
# Monkey-patch in our additional testing view
from myapp import urls
import copy
urls.oldpatterns = copy.copy(urls.urlpatterns)
urls.urlpatterns += urls.patterns('',
('^extra_test_view/$', self.extra_test_view),
)

def tearDown(self):
from myapp import urls
urls.urlpatterns = urls.oldpatterns
del urls.oldpatterns

Yuck. Obviously a better way to write this kind of test would be to
create a mock Request object within the test and pass it directly to
the view function:

def test_my_view(self):
view_func = ...
request = MockRequest(...)
response = view_func(request)
self.assert_( stuff on response )

It turns out the logic for building such a MockRequest is already
there, in django.test.Client - but it's coupled to the logic that
dispatches the created request through the URL conf. A simple subclass
fixes that:

http://www.djangosnippets.org/snippets/963/

So now I can do this:

factory = RequestFactory()
get_request = factory.get('/hello/')
post_request = factory.post('/submit/', {'foo': 'bar'})
response = view_func(get_request)
...

This makes testing views that aren't hooked in to the URL conf a ton
easier.

I'd suggest this for inclusion in Django, but it feels upside down.
The "create a mock request" functionality shouldn't be a subclass of
the "test a request against the urlconf" functionality - it should be
the other way round, or decoupled entirely.

As with the rest of the test framework, this is a great tool for
interactively exploring an application in the shell.

So, post 1.0 I think it's worth baking this functionality in to Django
itself, probably with a slight (backwards compatible) refactor of the
test Client code.

Cheers,

Simon

Russell Keith-Magee

unread,
Aug 13, 2008, 10:21:49 AM8/13/08
to django-d...@googlegroups.com
On Wed, Aug 13, 2008 at 7:48 PM, Simon Willison <si...@simonwillison.net> wrote:
>
> (Not at all important for 1.0, but it's on my mind at the moment)
>
> The django.test.Client test harness supports running tests against
> view functions that have been hooked in to the URL conf. While this is
> useful, I've stumbled across a number of cases where I've needed to
> test a view function which isn't wired in to the URL conf.
...

> So, post 1.0 I think it's worth baking this functionality in to Django
> itself, probably with a slight (backwards compatible) refactor of the
> test Client code.

Agreed. I like this approach, and I can certainly see the niche of
testing that it would suit very well. However, it will need to be a
post v1.0 activity. Please open a ticket so we don't forget about
this.

Yours,
Russ Magee %-)

akaihola

unread,
Sep 8, 2008, 1:03:24 AM9/8/08
to Django developers
I couldn't find a ticket for this issue yet. Simon, mind if I create a
ticket and dump your description of the issue there?

-Antti

Simon Willison

unread,
Sep 8, 2008, 1:58:28 AM9/8/08
to Django developers


On Sep 7, 10:03 pm, akaihola <akaih...@gmail.com> wrote:
> I couldn't find a ticket for this issue yet. Simon, mind if I create a
> ticket and dump your description of the issue there?

Go for it!

Simon Willison

unread,
Sep 9, 2008, 8:40:50 PM9/9/08
to Django developers
On Sep 8, 6:03 am, akaihola <akaih...@gmail.com> wrote:
> I couldn't find a ticket for this issue yet. Simon, mind if I create a
> ticket and dump your description of the issue there?

I've filed it here:

http://code.djangoproject.com/ticket/9002
Reply all
Reply to author
Forward
0 new messages