Ticket #17604: 17604-assertTemplateUsed.1.diff
File 17604-assertTemplateUsed.1.diff, 12.9 KB (added by , 13 years ago) |
---|
-
django/test/testcases.py
diff --git a/django/test/testcases.py b/django/test/testcases.py index 53ea02a..2e011e4 100644
a b from __future__ import with_statement 3 3 import os 4 4 import re 5 5 import sys 6 from copy import copy 6 7 from functools import wraps 7 8 from urlparse import urlsplit, urlunsplit 8 9 from xml.dom.minidom import parseString, Node … … from django.forms.fields import CharField 28 29 from django.http import QueryDict 29 30 from django.test import _doctest as doctest 30 31 from django.test.client import Client 32 from django.test.signals import template_rendered 31 33 from django.test.utils import (get_warnings_state, restore_warnings_state, 32 34 override_settings) 35 from django.test.utils import ContextList 33 36 from django.utils import simplejson, unittest as ut2 34 37 from django.utils.encoding import smart_str, force_unicode 35 38 from django.views.static import serve … … class _AssertNumQueriesContext(object): 260 263 ) 261 264 262 265 263 class SimpleTestCase(ut2.TestCase): 266 class _AssertTemplateUsedContext(object): 267 def __init__(self, test_case, template_name): 268 self.test_case = test_case 269 self.template_name = template_name 270 self.rendered_templates = [] 271 self.rendered_template_names = [] 272 self.context = ContextList() 273 274 def on_template_render(self, sender, signal, template, context, **kwargs): 275 self.rendered_templates.append(template) 276 self.rendered_template_names.append(template.name) 277 self.context.append(copy(context)) 278 279 def test(self): 280 return self.template_name in self.rendered_template_names 281 282 def message(self): 283 return u'%s was not rendered.' % self.template_name 284 285 def __enter__(self): 286 template_rendered.connect(self.on_template_render) 287 return self 288 289 def __exit__(self, exc_type, exc_value, traceback): 290 template_rendered.disconnect(self.on_template_render) 291 if exc_type is not None: 292 return 264 293 294 if not self.test(): 295 message = self.message() 296 if len(self.rendered_templates) == 0: 297 message += u' No template was rendered.' 298 else: 299 message += u' Following templates were rendered: %s' % ( 300 ', '.join(self.rendered_template_names)) 301 self.test_case.fail(message) 302 303 304 class _AssertTemplateNotUsedContext(_AssertTemplateUsedContext): 305 def test(self): 306 return self.template_name not in self.rendered_template_names 307 308 def message(self): 309 return u'%s was rendered.' % self.template_name 310 311 312 class SimpleTestCase(ut2.TestCase): 265 313 def save_warnings_state(self): 266 314 """ 267 315 Saves the state of the warnings module … … class TransactionTestCase(SimpleTestCase): 612 660 self.fail(msg_prefix + "The form '%s' was not used to render the" 613 661 " response" % form) 614 662 615 def assertTemplateUsed(self, response , template_name, msg_prefix=''):663 def assertTemplateUsed(self, response=None, template_name=None, msg_prefix=''): 616 664 """ 617 665 Asserts that the template with the provided name was used in rendering 618 the response. 666 the response. Also useable as context manager. 619 667 """ 668 if response is None and template_name is None: 669 raise TypeError(u'response and/or template_name argument must be provided') 670 620 671 if msg_prefix: 621 672 msg_prefix += ": " 622 673 674 # use assertTemplateUsed as context manager 675 if not hasattr(response, 'templates') or (response is None and template_name): 676 if response: 677 template_name = response 678 response = None 679 context = _AssertTemplateUsedContext(self, template_name) 680 return context 681 623 682 template_names = [t.name for t in response.templates] 624 683 if not template_names: 625 684 self.fail(msg_prefix + "No templates used to render the response") … … class TransactionTestCase(SimpleTestCase): 628 687 " the response. Actual template(s) used: %s" % 629 688 (template_name, u', '.join(template_names))) 630 689 631 def assertTemplateNotUsed(self, response , template_name, msg_prefix=''):690 def assertTemplateNotUsed(self, response=None, template_name=None, msg_prefix=''): 632 691 """ 633 692 Asserts that the template with the provided name was NOT used in 634 rendering the response. 693 rendering the response. Also useable as context manager. 635 694 """ 695 if response is None and template_name is None: 696 raise TypeError(u'response and/or template_name argument must be provided') 697 636 698 if msg_prefix: 637 699 msg_prefix += ": " 638 700 701 # use assertTemplateUsed as context manager 702 if not hasattr(response, 'templates') or (response is None and template_name): 703 if response: 704 template_name = response 705 response = None 706 context = _AssertTemplateNotUsedContext(self, template_name) 707 return context 708 639 709 template_names = [t.name for t in response.templates] 640 710 self.assertFalse(template_name in template_names, 641 711 msg_prefix + "Template '%s' was used unexpectedly in rendering" -
docs/releases/1.4.txt
diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt index 9b3c219..2c7cbf1 100644
a b apply URL escaping again. This is wrong for URLs whose unquoted form contains 942 942 a ``%xx`` sequence, but such URLs are very unlikely to happen in the wild, 943 943 since they would confuse browsers too. 944 944 945 ``assertTemplateUsed`` and ``assertTemplateNotUsed`` as context manager 946 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 947 948 It is now possible to check whether a template was used or not in a block of 949 code with the :meth:`~django.test.testcase.TestCase.assertTemplateUsed` and 950 :meth:`~django.test.testcase.TestCase.assertTemplateNotUsed` assertions. They 951 can be used as a context manager:: 952 953 with self.assertTemplateUsed('index.html'): 954 render_to_string('index.html') 955 with self.assertTemplateNotUsed('base.html'): 956 render_to_string('index.html') 957 958 See the :ref:`assertion documentation<assertions>` for more information. 959 945 960 Features deprecated in 1.4 946 961 ========================== 947 962 -
docs/topics/testing.txt
diff --git a/docs/topics/testing.txt b/docs/topics/testing.txt index ea2c52b..f0f0b44 100644
a b your test suite. 1575 1575 1576 1576 The name is a string such as ``'admin/index.html'``. 1577 1577 1578 .. versionadded:: 1.4 1579 1580 You can also use this as a context manager. The code that is executed 1581 under the with statement is then observed instead of a response:: 1582 1583 # This is necessary in Python 2.5 to enable the with statement, in 2.6 1584 # and up it is no longer necessary. 1585 from __future__ import with_statement 1586 1587 with self.assertTemplateUsed('index.html'): 1588 render_to_string('index.html') 1589 with self.assertTemplateUsed(template_name='index.html'): 1590 render_to_string('index.html') 1591 1578 1592 .. method:: TestCase.assertTemplateNotUsed(response, template_name, msg_prefix='') 1579 1593 1580 1594 Asserts that the template with the given name was *not* used in rendering 1581 1595 the response. 1582 1596 1597 .. versionadded:: 1.4 1598 1599 You can use this as a context manager in the same way as 1600 :func:`~TestCase.assertTemplateUsed`. 1601 1583 1602 .. method:: TestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='') 1584 1603 1585 1604 Asserts that the response return a ``status_code`` redirect status, it -
new file tests/regressiontests/test_utils/templates/template_used/extends.html
diff --git a/tests/regressiontests/test_utils/templates/template_used/alternative.html b/tests/regressiontests/test_utils/templates/template_used/alternative.html new file mode 100644 index 0000000..e69de29 diff --git a/tests/regressiontests/test_utils/templates/template_used/base.html b/tests/regressiontests/test_utils/templates/template_used/base.html new file mode 100644 index 0000000..e69de29 diff --git a/tests/regressiontests/test_utils/templates/template_used/extends.html b/tests/regressiontests/test_utils/templates/template_used/extends.html new file mode 100644 index 0000000..d14bfa2
- + 1 {% extends "template_used/base.html" %} -
new file tests/regressiontests/test_utils/templates/template_used/include.html
diff --git a/tests/regressiontests/test_utils/templates/template_used/include.html b/tests/regressiontests/test_utils/templates/template_used/include.html new file mode 100644 index 0000000..2d6c954
- + 1 {% include "template_used/base.html" %} -
tests/regressiontests/test_utils/tests.py
diff --git a/tests/regressiontests/test_utils/tests.py b/tests/regressiontests/test_utils/tests.py index eab6895..b578bff 100644
a b 1 1 from __future__ import with_statement, absolute_import 2 2 3 3 from django.forms import EmailField, IntegerField 4 from django.template.loader import render_to_string 4 5 from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature 5 6 from django.utils.unittest import skip 6 7 … … class AssertNumQueriesContextManagerTests(TestCase): 88 89 self.client.get("/test_utils/get_person/%s/" % person.pk) 89 90 90 91 92 class AssertTemplateUsedContextManagerTests(TestCase): 93 def test_usage(self): 94 with self.assertTemplateUsed('template_used/base.html'): 95 render_to_string('template_used/base.html') 96 97 with self.assertTemplateUsed(template_name='template_used/base.html'): 98 render_to_string('template_used/base.html') 99 100 with self.assertTemplateUsed('template_used/base.html'): 101 render_to_string('template_used/include.html') 102 103 with self.assertTemplateUsed('template_used/base.html'): 104 render_to_string('template_used/extends.html') 105 106 with self.assertTemplateUsed('template_used/base.html'): 107 render_to_string('template_used/base.html') 108 render_to_string('template_used/base.html') 109 110 def test_nested_usage(self): 111 with self.assertTemplateUsed('template_used/base.html'): 112 with self.assertTemplateUsed('template_used/include.html'): 113 render_to_string('template_used/include.html') 114 115 with self.assertTemplateUsed('template_used/extends.html'): 116 with self.assertTemplateUsed('template_used/base.html'): 117 render_to_string('template_used/extends.html') 118 119 with self.assertTemplateUsed('template_used/base.html'): 120 with self.assertTemplateUsed('template_used/alternative.html'): 121 render_to_string('template_used/alternative.html') 122 render_to_string('template_used/base.html') 123 124 with self.assertTemplateUsed('template_used/base.html'): 125 render_to_string('template_used/extends.html') 126 with self.assertTemplateNotUsed('template_used/base.html'): 127 render_to_string('template_used/alternative.html') 128 render_to_string('template_used/base.html') 129 130 def test_not_used(self): 131 with self.assertTemplateNotUsed('template_used/base.html'): 132 pass 133 with self.assertTemplateNotUsed('template_used/alternative.html'): 134 pass 135 136 def test_error_message(self): 137 try: 138 with self.assertTemplateUsed('template_used/base.html'): 139 pass 140 except AssertionError, e: 141 self.assertTrue('template_used/base.html' in e.message) 142 143 try: 144 with self.assertTemplateUsed(template_name='template_used/base.html'): 145 pass 146 except AssertionError, e: 147 self.assertTrue('template_used/base.html' in e.message) 148 149 try: 150 with self.assertTemplateUsed('template_used/base.html'): 151 render_to_string('template_used/alternative.html') 152 except AssertionError, e: 153 self.assertTrue('template_used/base.html' in e.message, e.message) 154 self.assertTrue('template_used/alternative.html' in e.message, e.message) 155 156 def test_failure(self): 157 with self.assertRaises(TypeError): 158 with self.assertTemplateUsed(): 159 pass 160 161 with self.assertRaises(AssertionError): 162 with self.assertTemplateUsed(''): 163 pass 164 165 with self.assertRaises(AssertionError): 166 with self.assertTemplateUsed(''): 167 render_to_string('template_used/base.html') 168 169 with self.assertRaises(AssertionError): 170 with self.assertTemplateUsed(template_name=''): 171 pass 172 173 with self.assertRaises(AssertionError): 174 with self.assertTemplateUsed('template_used/base.html'): 175 render_to_string('template_used/alternative.html') 176 177 91 178 class SaveRestoreWarningState(TestCase): 92 179 def test_save_restore_warnings_state(self): 93 180 """