Skip to content

Commit 7ca9d93

Browse files
committed
Fixed #10314 -- Added a message prefix argument to Django's test assertions. Thanks to Wes Winham for the original suggestion, and Chistian Oudard for the patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@12273 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 1b3dc8a commit 7ca9d93

File tree

4 files changed

+198
-56
lines changed

4 files changed

+198
-56
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ answer newbie questions, and generally made Django that much better:
339339
Afonso Fernández Nogueira <[email protected]>
340340
Neal Norwitz <[email protected]>
341341
Todd O'Bryan <[email protected]>
342+
Christian Oudard <[email protected]>
342343
oggie rob <[email protected]>
343344
344345
Jay Parlar <[email protected]>

django/test/testcases.py

Lines changed: 74 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -287,34 +287,41 @@ def _urlconf_teardown(self):
287287
clear_url_caches()
288288

289289
def assertRedirects(self, response, expected_url, status_code=302,
290-
target_status_code=200, host=None):
290+
target_status_code=200, host=None, msg_prefix=''):
291291
"""Asserts that a response redirected to a specific URL, and that the
292292
redirect URL can be loaded.
293293
294294
Note that assertRedirects won't work for external links since it uses
295295
TestClient to do a request.
296296
"""
297+
if msg_prefix:
298+
msg_prefix += ": "
299+
297300
if hasattr(response, 'redirect_chain'):
298301
# The request was a followed redirect
299302
self.failUnless(len(response.redirect_chain) > 0,
300-
("Response didn't redirect as expected: Response code was %d"
301-
" (expected %d)" % (response.status_code, status_code)))
303+
msg_prefix + "Response didn't redirect as expected: Response"
304+
" code was %d (expected %d)" %
305+
(response.status_code, status_code))
302306

303307
self.assertEqual(response.redirect_chain[0][1], status_code,
304-
("Initial response didn't redirect as expected: Response code was %d"
305-
" (expected %d)" % (response.redirect_chain[0][1], status_code)))
308+
msg_prefix + "Initial response didn't redirect as expected:"
309+
" Response code was %d (expected %d)" %
310+
(response.redirect_chain[0][1], status_code))
306311

307312
url, status_code = response.redirect_chain[-1]
308313

309314
self.assertEqual(response.status_code, target_status_code,
310-
("Response didn't redirect as expected: Final Response code was %d"
311-
" (expected %d)" % (response.status_code, target_status_code)))
315+
msg_prefix + "Response didn't redirect as expected: Final"
316+
" Response code was %d (expected %d)" %
317+
(response.status_code, target_status_code))
312318

313319
else:
314320
# Not a followed redirect
315321
self.assertEqual(response.status_code, status_code,
316-
("Response didn't redirect as expected: Response code was %d"
317-
" (expected %d)" % (response.status_code, status_code)))
322+
msg_prefix + "Response didn't redirect as expected: Response"
323+
" code was %d (expected %d)" %
324+
(response.status_code, status_code))
318325

319326
url = response['Location']
320327
scheme, netloc, path, query, fragment = urlsplit(url)
@@ -324,63 +331,74 @@ def assertRedirects(self, response, expected_url, status_code=302,
324331
# Get the redirection page, using the same client that was used
325332
# to obtain the original response.
326333
self.assertEqual(redirect_response.status_code, target_status_code,
327-
("Couldn't retrieve redirection page '%s': response code was %d"
328-
" (expected %d)") %
329-
(path, redirect_response.status_code, target_status_code))
334+
msg_prefix + "Couldn't retrieve redirection page '%s':"
335+
" response code was %d (expected %d)" %
336+
(path, redirect_response.status_code, target_status_code))
330337

331338
e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit(expected_url)
332339
if not (e_scheme or e_netloc):
333340
expected_url = urlunsplit(('http', host or 'testserver', e_path,
334341
e_query, e_fragment))
335342

336343
self.assertEqual(url, expected_url,
337-
"Response redirected to '%s', expected '%s'" % (url, expected_url))
338-
344+
msg_prefix + "Response redirected to '%s', expected '%s'" %
345+
(url, expected_url))
339346

340-
def assertContains(self, response, text, count=None, status_code=200):
347+
def assertContains(self, response, text, count=None, status_code=200,
348+
msg_prefix=''):
341349
"""
342350
Asserts that a response indicates that a page was retrieved
343351
successfully, (i.e., the HTTP status code was as expected), and that
344352
``text`` occurs ``count`` times in the content of the response.
345353
If ``count`` is None, the count doesn't matter - the assertion is true
346354
if the text occurs at least once in the response.
347355
"""
356+
if msg_prefix:
357+
msg_prefix += ": "
358+
348359
self.assertEqual(response.status_code, status_code,
349-
"Couldn't retrieve page: Response code was %d (expected %d)'" %
350-
(response.status_code, status_code))
360+
msg_prefix + "Couldn't retrieve page: Response code was %d"
361+
" (expected %d)" % (response.status_code, status_code))
351362
text = smart_str(text, response._charset)
352363
real_count = response.content.count(text)
353364
if count is not None:
354365
self.assertEqual(real_count, count,
355-
"Found %d instances of '%s' in response (expected %d)" %
356-
(real_count, text, count))
366+
msg_prefix + "Found %d instances of '%s' in response"
367+
" (expected %d)" % (real_count, text, count))
357368
else:
358369
self.failUnless(real_count != 0,
359-
"Couldn't find '%s' in response" % text)
370+
msg_prefix + "Couldn't find '%s' in response" % text)
360371

361-
def assertNotContains(self, response, text, status_code=200):
372+
def assertNotContains(self, response, text, status_code=200,
373+
msg_prefix=''):
362374
"""
363375
Asserts that a response indicates that a page was retrieved
364376
successfully, (i.e., the HTTP status code was as expected), and that
365377
``text`` doesn't occurs in the content of the response.
366378
"""
379+
if msg_prefix:
380+
msg_prefix += ": "
381+
367382
self.assertEqual(response.status_code, status_code,
368-
"Couldn't retrieve page: Response code was %d (expected %d)'" %
369-
(response.status_code, status_code))
383+
msg_prefix + "Couldn't retrieve page: Response code was %d"
384+
" (expected %d)" % (response.status_code, status_code))
370385
text = smart_str(text, response._charset)
371-
self.assertEqual(response.content.count(text),
372-
0, "Response should not contain '%s'" % text)
386+
self.assertEqual(response.content.count(text), 0,
387+
msg_prefix + "Response should not contain '%s'" % text)
373388

374-
def assertFormError(self, response, form, field, errors):
389+
def assertFormError(self, response, form, field, errors, msg_prefix=''):
375390
"""
376391
Asserts that a form used to render the response has a specific field
377392
error.
378393
"""
394+
if msg_prefix:
395+
msg_prefix += ": "
396+
379397
# Put context(s) into a list to simplify processing.
380398
contexts = to_list(response.context)
381399
if not contexts:
382-
self.fail('Response did not use any contexts to render the'
383-
' response')
400+
self.fail(msg_prefix + "Response did not use any contexts to"
401+
"render the response")
384402

385403
# Put error(s) into a list to simplify processing.
386404
errors = to_list(errors)
@@ -396,50 +414,57 @@ def assertFormError(self, response, form, field, errors):
396414
if field in context[form].errors:
397415
field_errors = context[form].errors[field]
398416
self.failUnless(err in field_errors,
399-
"The field '%s' on form '%s' in"
400-
" context %d does not contain the"
401-
" error '%s' (actual errors: %s)" %
402-
(field, form, i, err,
403-
repr(field_errors)))
417+
msg_prefix + "The field '%s' on form '%s' in"
418+
" context %d does not contain the error '%s'"
419+
" (actual errors: %s)" %
420+
(field, form, i, err, repr(field_errors)))
404421
elif field in context[form].fields:
405-
self.fail("The field '%s' on form '%s' in context %d"
406-
" contains no errors" % (field, form, i))
422+
self.fail(msg_prefix + "The field '%s' on form '%s'"
423+
" in context %d contains no errors" %
424+
(field, form, i))
407425
else:
408-
self.fail("The form '%s' in context %d does not"
409-
" contain the field '%s'" %
426+
self.fail(msg_prefix + "The form '%s' in context %d"
427+
" does not contain the field '%s'" %
410428
(form, i, field))
411429
else:
412430
non_field_errors = context[form].non_field_errors()
413431
self.failUnless(err in non_field_errors,
414-
"The form '%s' in context %d does not contain the"
415-
" non-field error '%s' (actual errors: %s)" %
432+
msg_prefix + "The form '%s' in context %d does not"
433+
" contain the non-field error '%s'"
434+
" (actual errors: %s)" %
416435
(form, i, err, non_field_errors))
417436
if not found_form:
418-
self.fail("The form '%s' was not used to render the response" %
419-
form)
437+
self.fail(msg_prefix + "The form '%s' was not used to render the"
438+
" response" % form)
420439

421-
def assertTemplateUsed(self, response, template_name):
440+
def assertTemplateUsed(self, response, template_name, msg_prefix=''):
422441
"""
423442
Asserts that the template with the provided name was used in rendering
424443
the response.
425444
"""
445+
if msg_prefix:
446+
msg_prefix += ": "
447+
426448
template_names = [t.name for t in to_list(response.template)]
427449
if not template_names:
428-
self.fail('No templates used to render the response')
450+
self.fail(msg_prefix + "No templates used to render the response")
429451
self.failUnless(template_name in template_names,
430-
(u"Template '%s' was not a template used to render the response."
431-
u" Actual template(s) used: %s") % (template_name,
432-
u', '.join(template_names)))
452+
msg_prefix + "Template '%s' was not a template used to render"
453+
" the response. Actual template(s) used: %s" %
454+
(template_name, u', '.join(template_names)))
433455

434-
def assertTemplateNotUsed(self, response, template_name):
456+
def assertTemplateNotUsed(self, response, template_name, msg_prefix=''):
435457
"""
436458
Asserts that the template with the provided name was NOT used in
437459
rendering the response.
438460
"""
461+
if msg_prefix:
462+
msg_prefix += ": "
463+
439464
template_names = [t.name for t in to_list(response.template)]
440465
self.failIf(template_name in template_names,
441-
(u"Template '%s' was used unexpectedly in rendering the"
442-
u" response") % template_name)
466+
msg_prefix + "Template '%s' was used unexpectedly in rendering"
467+
" the response" % template_name)
443468

444469
def connections_support_transactions():
445470
"""

docs/topics/testing.txt

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,23 +1104,32 @@ Assertions
11041104

11051105
.. versionadded:: 1.0
11061106

1107+
.. versionchanged:: 1.2
1108+
Addded ``msg_prefix`` argument.
1109+
11071110
As Python's normal ``unittest.TestCase`` class implements assertion methods
11081111
such as ``assertTrue`` and ``assertEquals``, Django's custom ``TestCase`` class
11091112
provides a number of custom assertion methods that are useful for testing Web
11101113
applications:
11111114

1112-
.. method:: TestCase.assertContains(response, text, count=None, status_code=200)
1115+
The failure messages given by the assertion methods can be customized
1116+
with the ``msg_prefix`` argument. This string will be prefixed to any
1117+
failure message generated by the assertion. This allows you to provide
1118+
additional details that may help you to identify the location and
1119+
cause of an failure in your test suite.
1120+
1121+
.. method:: TestCase.assertContains(response, text, count=None, status_code=200, msg_prefix='')
11131122

11141123
Asserts that a ``Response`` instance produced the given ``status_code`` and
11151124
that ``text`` appears in the content of the response. If ``count`` is
11161125
provided, ``text`` must occur exactly ``count`` times in the response.
11171126

1118-
.. method:: TestCase.assertNotContains(response, text, status_code=200)
1127+
.. method:: TestCase.assertNotContains(response, text, status_code=200, msg_prefix='')
11191128

11201129
Asserts that a ``Response`` instance produced the given ``status_code`` and
11211130
that ``text`` does not appears in the content of the response.
11221131

1123-
.. method:: TestCase.assertFormError(response, form, field, errors)
1132+
.. method:: TestCase.assertFormError(response, form, field, errors, msg_prefix='')
11241133

11251134
Asserts that a field on a form raises the provided list of errors when
11261135
rendered on the form.
@@ -1135,19 +1144,19 @@ applications:
11351144
``errors`` is an error string, or a list of error strings, that are
11361145
expected as a result of form validation.
11371146

1138-
.. method:: TestCase.assertTemplateUsed(response, template_name)
1147+
.. method:: TestCase.assertTemplateUsed(response, template_name, msg_prefix='')
11391148

11401149
Asserts that the template with the given name was used in rendering the
11411150
response.
11421151

11431152
The name is a string such as ``'admin/index.html'``.
11441153

1145-
.. method:: TestCase.assertTemplateNotUsed(response, template_name)
1154+
.. method:: TestCase.assertTemplateNotUsed(response, template_name, msg_prefix='')
11461155

11471156
Asserts that the template with the given name was *not* used in rendering
11481157
the response.
11491158

1150-
.. method:: TestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200)
1159+
.. method:: TestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='')
11511160

11521161
Asserts that the response return a ``status_code`` redirect status, it
11531162
redirected to ``expected_url`` (including any GET data), and the final

0 commit comments

Comments
 (0)