Fixed #21598 -- cleaned up template loader overrides in tests

- Template loader overriding is managed with contexts.
- The test loader is a class (function based loaders entered deprecation timeline
  in 1.4).
- Template loader overrider that overrides with test loader added.
This commit is contained in:
Unai Zalakain 2013-12-12 10:59:05 +01:00 committed by Tim Graham
parent 756c390fb5
commit 4dc4d12e27
4 changed files with 214 additions and 193 deletions

View File

@ -146,42 +146,107 @@ def get_runner(settings, test_runner_class=None):
return test_runner return test_runner
def setup_test_template_loader(templates_dict, use_cached_loader=False): class override_template_loaders(object):
""" """
Changes Django to only find templates from within a dictionary (where each Acts as a function decorator, context manager or start/end manager and
key is the template name and each value is the corresponding template override the template loaders. It could be used in the following ways:
content to return).
Use meth:`restore_template_loaders` to restore the original loaders. @override_template_loaders(SomeLoader())
def test_function(self):
...
with override_template_loaders(SomeLoader(), OtherLoader()) as loaders:
...
loaders = override_template_loaders.override(SomeLoader())
...
override_template_loaders.restore()
""" """
if hasattr(loader, RESTORE_LOADERS_ATTR): def __init__(self, *loaders):
raise Exception("loader.%s already exists" % RESTORE_LOADERS_ATTR) self.loaders = loaders
self.old_loaders = []
def test_template_loader(template_name, template_dirs=None): def __enter__(self):
"A custom template loader that loads templates from a dictionary." self.old_loaders = loader.template_source_loaders
loader.template_source_loaders = self.loaders
return self.loaders
def __exit__(self, type, value, traceback):
loader.template_source_loaders = self.old_loaders
def __call__(self, test_func):
@wraps(test_func)
def inner(*args, **kwargs):
with self:
return test_func(*args, **kwargs)
return inner
@classmethod
def override(cls, *loaders):
if hasattr(loader, RESTORE_LOADERS_ATTR):
raise Exception("loader.%s already exists" % RESTORE_LOADERS_ATTR)
setattr(loader, RESTORE_LOADERS_ATTR, loader.template_source_loaders)
loader.template_source_loaders = loaders
return loaders
@classmethod
def restore(cls):
loader.template_source_loaders = getattr(loader, RESTORE_LOADERS_ATTR)
delattr(loader, RESTORE_LOADERS_ATTR)
class TestTemplateLoader(loader.BaseLoader):
"A custom template loader that loads templates from a dictionary."
is_usable = True
def __init__(self, templates_dict):
self.templates_dict = templates_dict
def load_template_source(self, template_name, template_dirs=None,
skip_template=None):
try: try:
return (templates_dict[template_name], "test:%s" % template_name) return (self.templates_dict[template_name],
"test:%s" % template_name)
except KeyError: except KeyError:
raise TemplateDoesNotExist(template_name) raise TemplateDoesNotExist(template_name)
if use_cached_loader:
template_loader = cached.Loader(('test_template_loader',))
template_loader._cached_loaders = (test_template_loader,)
else:
template_loader = test_template_loader
setattr(loader, RESTORE_LOADERS_ATTR, loader.template_source_loaders) class override_with_test_loader(override_template_loaders):
loader.template_source_loaders = (template_loader,)
return template_loader
def restore_template_loaders():
""" """
Restores the original template loaders after Acts as a function decorator, context manager or start/end manager and
:meth:`setup_test_template_loader` has been run. override the template loaders with the test loader. It could be used in the
following ways:
@override_with_test_loader(templates_dict, use_cached_loader=True)
def test_function(self):
...
with override_with_test_loader(templates_dict) as test_loader:
...
test_loader = override_with_test_loader.override(templates_dict)
...
override_with_test_loader.restore()
""" """
loader.template_source_loaders = getattr(loader, RESTORE_LOADERS_ATTR)
delattr(loader, RESTORE_LOADERS_ATTR) def __init__(self, templates_dict, use_cached_loader=False):
self.loader = self._get_loader(templates_dict, use_cached_loader)
super(override_with_test_loader, self).__init__(self.loader)
def __enter__(self):
return super(override_with_test_loader, self).__enter__()[0]
@classmethod
def override(cls, templates_dict, use_cached_loader=False):
loader = cls._get_loader(templates_dict, use_cached_loader)
return super(override_with_test_loader, cls).override(loader)[0]
@classmethod
def _get_loader(cls, templates_dict, use_cached_loader=False):
if use_cached_loader:
loader = cached.Loader(('TestTemplateLoader',))
loader._cached_loaders = TestTemplateLoader(templates_dict)
return TestTemplateLoader(templates_dict)
class override_settings(object): class override_settings(object):

View File

@ -15,8 +15,8 @@ from django.template import (base as template_base, loader, Context,
RequestContext, Template, TemplateSyntaxError) RequestContext, Template, TemplateSyntaxError)
from django.template.loaders import app_directories, filesystem, cached from django.template.loaders import app_directories, filesystem, cached
from django.test import RequestFactory, TestCase from django.test import RequestFactory, TestCase
from django.test.utils import (setup_test_template_loader, from django.test.utils import (override_settings, override_template_loaders,
restore_template_loaders, override_settings, extend_sys_path) override_with_test_loader, extend_sys_path)
from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from django.utils.formats import date_format from django.utils.formats import date_format
@ -208,42 +208,36 @@ class TemplateLoaderTests(TestCase):
test_template_sources('/DIR1/index.HTML', template_dirs, test_template_sources('/DIR1/index.HTML', template_dirs,
['/DIR1/index.HTML']) ['/DIR1/index.HTML'])
@override_template_loaders(filesystem.Loader())
# Turn TEMPLATE_DEBUG on, so that the origin file name will be kept with # Turn TEMPLATE_DEBUG on, so that the origin file name will be kept with
# the compiled templates. # the compiled templates.
@override_settings(TEMPLATE_DEBUG=True) @override_settings(TEMPLATE_DEBUG=True)
def test_loader_debug_origin(self): def test_loader_debug_origin(self):
old_loaders = loader.template_source_loaders # We rely on the fact that runtests.py sets up TEMPLATE_DIRS to
# point to a directory containing a login.html file. Also that
# the file system and app directories loaders both inherit the
# load_template method from the BaseLoader class, so we only need
# to test one of them.
load_name = 'login.html'
template = loader.get_template(load_name)
template_name = template.nodelist[0].source[0].name
self.assertTrue(template_name.endswith(load_name),
'Template loaded by filesystem loader has incorrect name for debug page: %s' % template_name)
try: # Also test the cached loader, since it overrides load_template
loader.template_source_loaders = (filesystem.Loader(),) cache_loader = cached.Loader(('',))
cache_loader._cached_loaders = loader.template_source_loaders
loader.template_source_loaders = (cache_loader,)
# We rely on the fact that runtests.py sets up TEMPLATE_DIRS to template = loader.get_template(load_name)
# point to a directory containing a login.html file. Also that template_name = template.nodelist[0].source[0].name
# the file system and app directories loaders both inherit the self.assertTrue(template_name.endswith(load_name),
# load_template method from the BaseLoader class, so we only need 'Template loaded through cached loader has incorrect name for debug page: %s' % template_name)
# to test one of them.
load_name = 'login.html'
template = loader.get_template(load_name)
template_name = template.nodelist[0].source[0].name
self.assertTrue(template_name.endswith(load_name),
'Template loaded by filesystem loader has incorrect name for debug page: %s' % template_name)
# Also test the cached loader, since it overrides load_template template = loader.get_template(load_name)
cache_loader = cached.Loader(('',)) template_name = template.nodelist[0].source[0].name
cache_loader._cached_loaders = loader.template_source_loaders self.assertTrue(template_name.endswith(load_name),
loader.template_source_loaders = (cache_loader,) 'Cached template loaded through cached loader has incorrect name for debug page: %s' % template_name)
template = loader.get_template(load_name)
template_name = template.nodelist[0].source[0].name
self.assertTrue(template_name.endswith(load_name),
'Template loaded through cached loader has incorrect name for debug page: %s' % template_name)
template = loader.get_template(load_name)
template_name = template.nodelist[0].source[0].name
self.assertTrue(template_name.endswith(load_name),
'Cached template loaded through cached loader has incorrect name for debug page: %s' % template_name)
finally:
loader.template_source_loaders = old_loaders
def test_loader_origin(self): def test_loader_origin(self):
with self.settings(TEMPLATE_DEBUG=True): with self.settings(TEMPLATE_DEBUG=True):
@ -262,33 +256,31 @@ class TemplateLoaderTests(TestCase):
# TEMPLATE_DEBUG must be true, otherwise the exception raised # TEMPLATE_DEBUG must be true, otherwise the exception raised
# during {% include %} processing will be suppressed. # during {% include %} processing will be suppressed.
@override_settings(TEMPLATE_DEBUG=True) @override_settings(TEMPLATE_DEBUG=True)
# Test the base loader class via the app loader. load_template
# from base is used by all shipped loaders excepting cached,
# which has its own test.
@override_template_loaders(app_directories.Loader())
def test_include_missing_template(self): def test_include_missing_template(self):
""" """
Tests that the correct template is identified as not existing Tests that the correct template is identified as not existing
when {% include %} specifies a template that does not exist. when {% include %} specifies a template that does not exist.
""" """
old_loaders = loader.template_source_loaders load_name = 'test_include_error.html'
r = None
try: try:
# Test the base loader class via the app loader. load_template tmpl = loader.select_template([load_name])
# from base is used by all shipped loaders excepting cached, r = tmpl.render(template.Context({}))
# which has its own test. except template.TemplateDoesNotExist as e:
loader.template_source_loaders = (app_directories.Loader(),) self.assertEqual(e.args[0], 'missing.html')
self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r)
load_name = 'test_include_error.html'
r = None
try:
tmpl = loader.select_template([load_name])
r = tmpl.render(template.Context({}))
except template.TemplateDoesNotExist as e:
self.assertEqual(e.args[0], 'missing.html')
self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r)
finally:
loader.template_source_loaders = old_loaders
# TEMPLATE_DEBUG must be true, otherwise the exception raised # TEMPLATE_DEBUG must be true, otherwise the exception raised
# during {% include %} processing will be suppressed. # during {% include %} processing will be suppressed.
@override_settings(TEMPLATE_DEBUG=True) @override_settings(TEMPLATE_DEBUG=True)
# Test the base loader class via the app loader. load_template
# from base is used by all shipped loaders excepting cached,
# which has its own test.
@override_template_loaders(app_directories.Loader())
def test_extends_include_missing_baseloader(self): def test_extends_include_missing_baseloader(self):
""" """
Tests that the correct template is identified as not existing Tests that the correct template is identified as not existing
@ -296,24 +288,14 @@ class TemplateLoaderTests(TestCase):
that template has an {% include %} of something that does not that template has an {% include %} of something that does not
exist. See #12787. exist. See #12787.
""" """
old_loaders = loader.template_source_loaders load_name = 'test_extends_error.html'
tmpl = loader.get_template(load_name)
r = None
try: try:
# Test the base loader class via the app loader. load_template r = tmpl.render(template.Context({}))
# from base is used by all shipped loaders excepting cached, except template.TemplateDoesNotExist as e:
# which has its own test. self.assertEqual(e.args[0], 'missing.html')
loader.template_source_loaders = (app_directories.Loader(),) self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r)
load_name = 'test_extends_error.html'
tmpl = loader.get_template(load_name)
r = None
try:
r = tmpl.render(template.Context({}))
except template.TemplateDoesNotExist as e:
self.assertEqual(e.args[0], 'missing.html')
self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r)
finally:
loader.template_source_loaders = old_loaders
@override_settings(TEMPLATE_DEBUG=True) @override_settings(TEMPLATE_DEBUG=True)
def test_extends_include_missing_cachedloader(self): def test_extends_include_missing_cachedloader(self):
@ -321,14 +303,9 @@ class TemplateLoaderTests(TestCase):
Same as test_extends_include_missing_baseloader, only tests Same as test_extends_include_missing_baseloader, only tests
behavior of the cached loader instead of BaseLoader. behavior of the cached loader instead of BaseLoader.
""" """
cache_loader = cached.Loader(('',))
old_loaders = loader.template_source_loaders cache_loader._cached_loaders = (app_directories.Loader(),)
with override_template_loaders(cache_loader,):
try:
cache_loader = cached.Loader(('',))
cache_loader._cached_loaders = (app_directories.Loader(),)
loader.template_source_loaders = (cache_loader,)
load_name = 'test_extends_error.html' load_name = 'test_extends_error.html'
tmpl = loader.get_template(load_name) tmpl = loader.get_template(load_name)
r = None r = None
@ -346,8 +323,6 @@ class TemplateLoaderTests(TestCase):
except template.TemplateDoesNotExist as e: except template.TemplateDoesNotExist as e:
self.assertEqual(e.args[0], 'missing.html') self.assertEqual(e.args[0], 'missing.html')
self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r) self.assertEqual(r, None, 'Template rendering unexpectedly succeeded, produced: ->%r<-' % r)
finally:
loader.template_source_loaders = old_loaders
def test_include_template_argument(self): def test_include_template_argument(self):
""" """
@ -544,89 +519,83 @@ class TemplateTests(TestCase):
template_tests.update(filter_tests) template_tests.update(filter_tests)
cache_loader = setup_test_template_loader( templates = dict((name, t[0]) for name, t in six.iteritems(template_tests))
dict((name, t[0]) for name, t in six.iteritems(template_tests)), with override_with_test_loader(templates, use_cached_loader=True) as cache_loader:
use_cached_loader=True, failures = []
) tests = sorted(template_tests.items())
failures = [] # Set TEMPLATE_STRING_IF_INVALID to a known string.
tests = sorted(template_tests.items()) expected_invalid_str = 'INVALID'
# Set TEMPLATE_STRING_IF_INVALID to a known string. # Warm the URL reversing cache. This ensures we don't pay the cost
expected_invalid_str = 'INVALID' # warming the cache during one of the tests.
urlresolvers.reverse('template_tests.views.client_action',
kwargs={'id': 0, 'action': "update"})
# Warm the URL reversing cache. This ensures we don't pay the cost for name, vals in tests:
# warming the cache during one of the tests. if isinstance(vals[2], tuple):
urlresolvers.reverse('template_tests.views.client_action', normal_string_result = vals[2][0]
kwargs={'id': 0, 'action': "update"}) invalid_string_result = vals[2][1]
for name, vals in tests: if isinstance(invalid_string_result, tuple):
if isinstance(vals[2], tuple): expected_invalid_str = 'INVALID %s'
normal_string_result = vals[2][0] invalid_string_result = invalid_string_result[0] % invalid_string_result[1]
invalid_string_result = vals[2][1] template_base.invalid_var_format_string = True
if isinstance(invalid_string_result, tuple): try:
expected_invalid_str = 'INVALID %s' template_debug_result = vals[2][2]
invalid_string_result = invalid_string_result[0] % invalid_string_result[1] except IndexError:
template_base.invalid_var_format_string = True template_debug_result = normal_string_result
try: else:
template_debug_result = vals[2][2] normal_string_result = vals[2]
except IndexError: invalid_string_result = vals[2]
template_debug_result = normal_string_result template_debug_result = vals[2]
else: with translation.override(vals[1].get('LANGUAGE_CODE', 'en-us')):
normal_string_result = vals[2] for invalid_str, template_debug, result in [
invalid_string_result = vals[2] ('', False, normal_string_result),
template_debug_result = vals[2] (expected_invalid_str, False, invalid_string_result),
('', True, template_debug_result)
with translation.override(vals[1].get('LANGUAGE_CODE', 'en-us')): ]:
with override_settings(TEMPLATE_STRING_IF_INVALID=invalid_str,
for invalid_str, template_debug, result in [ TEMPLATE_DEBUG=template_debug):
('', False, normal_string_result), for is_cached in (False, True):
(expected_invalid_str, False, invalid_string_result),
('', True, template_debug_result)
]:
with override_settings(TEMPLATE_STRING_IF_INVALID=invalid_str,
TEMPLATE_DEBUG=template_debug):
for is_cached in (False, True):
try:
try: try:
with warnings.catch_warnings(): try:
# Ignore pending deprecations of loading 'ssi' and 'url' tags from future. with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=RemovedInDjango19Warning, module='django.templatetags.future') # Ignore pending deprecations of loading 'ssi' and 'url' tags from future.
# Ignore deprecations of loading 'cycle' and 'firstof' tags from future. warnings.filterwarnings("ignore", category=RemovedInDjango19Warning, module='django.templatetags.future')
warnings.filterwarnings("ignore", category=RemovedInDjango20Warning, module="django.templatetags.future") # Ignore deprecations of loading 'cycle' and 'firstof' tags from future.
test_template = loader.get_template(name) warnings.filterwarnings("ignore", category=RemovedInDjango20Warning, module="django.templatetags.future")
except ShouldNotExecuteException: test_template = loader.get_template(name)
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Template loading invoked method that shouldn't have been invoked." % (is_cached, invalid_str, template_debug, name)) except ShouldNotExecuteException:
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Template loading invoked method that shouldn't have been invoked." % (is_cached, invalid_str, template_debug, name))
try: try:
with warnings.catch_warnings(): with warnings.catch_warnings():
# Ignore deprecations of using the wrong number of variables with the 'for' tag. # Ignore deprecations of using the wrong number of variables with the 'for' tag.
warnings.filterwarnings("ignore", category=RemovedInDjango20Warning, module="django.template.defaulttags") warnings.filterwarnings("ignore", category=RemovedInDjango20Warning, module="django.template.defaulttags")
output = self.render(test_template, vals) output = self.render(test_template, vals)
except ShouldNotExecuteException: except ShouldNotExecuteException:
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Template rendering invoked method that shouldn't have been invoked." % (is_cached, invalid_str, template_debug, name)) failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Template rendering invoked method that shouldn't have been invoked." % (is_cached, invalid_str, template_debug, name))
except ContextStackException: except ContextStackException:
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Context stack was left imbalanced" % (is_cached, invalid_str, template_debug, name)) failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Context stack was left imbalanced" % (is_cached, invalid_str, template_debug, name))
continue continue
except Exception: except Exception:
exc_type, exc_value, exc_tb = sys.exc_info() exc_type, exc_value, exc_tb = sys.exc_info()
if exc_type != result: if exc_type != result:
tb = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_tb)) tb = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_tb))
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Got %s, exception: %s\n%s" % (is_cached, invalid_str, template_debug, name, exc_type, exc_value, tb)) failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Got %s, exception: %s\n%s" % (is_cached, invalid_str, template_debug, name, exc_type, exc_value, tb))
continue continue
if output != result: if output != result:
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Expected %r, got %r" % (is_cached, invalid_str, template_debug, name, result, output)) failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Expected %r, got %r" % (is_cached, invalid_str, template_debug, name, result, output))
cache_loader.reset() cache_loader.reset()
if template_base.invalid_var_format_string: if template_base.invalid_var_format_string:
expected_invalid_str = 'INVALID' expected_invalid_str = 'INVALID'
template_base.invalid_var_format_string = False template_base.invalid_var_format_string = False
restore_template_loaders()
self.assertEqual(failures, [], "Tests failed:\n%s\n%s" % self.assertEqual(failures, [], "Tests failed:\n%s\n%s" %
('-' * 70, ("\n%s\n" % ('-' * 70)).join(failures))) ('-' * 70, ("\n%s\n" % ('-' * 70)).join(failures)))
@ -1887,13 +1856,13 @@ class RequestContextTests(unittest.TestCase):
def setUp(self): def setUp(self):
templates = { templates = {
'child': Template('{{ var|default:"none" }}'), 'child': '{{ var|default:"none" }}',
} }
setup_test_template_loader(templates) override_with_test_loader.override(templates)
self.fake_request = RequestFactory().get('/') self.fake_request = RequestFactory().get('/')
def tearDown(self): def tearDown(self):
restore_template_loaders() override_with_test_loader.restore()
def test_include_only(self): def test_include_only(self):
""" """

View File

@ -17,8 +17,7 @@ from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.template.base import TemplateDoesNotExist from django.template.base import TemplateDoesNotExist
from django.test import TestCase, RequestFactory, override_settings from django.test import TestCase, RequestFactory, override_settings
from django.test.utils import ( from django.test.utils import override_with_test_loader
setup_test_template_loader, restore_template_loaders)
from django.utils.encoding import force_text, force_bytes from django.utils.encoding import force_text, force_bytes
from django.utils import six from django.utils import six
from django.views.debug import ExceptionReporter from django.views.debug import ExceptionReporter
@ -47,23 +46,16 @@ class DebugViewTests(TestCase):
def test_403(self): def test_403(self):
# Ensure no 403.html template exists to test the default case. # Ensure no 403.html template exists to test the default case.
setup_test_template_loader({}) with override_with_test_loader({}):
try:
response = self.client.get('/raises403/') response = self.client.get('/raises403/')
self.assertContains(response, '<h1>403 Forbidden</h1>', status_code=403) self.assertContains(response, '<h1>403 Forbidden</h1>', status_code=403)
finally:
restore_template_loaders()
def test_403_template(self): def test_403_template(self):
# Set up a test 403.html template. # Set up a test 403.html template.
setup_test_template_loader( with override_with_test_loader({'403.html': 'This is a test template '
{'403.html': 'This is a test template for a 403 Forbidden error.'} 'for a 403 Forbidden error.'}):
)
try:
response = self.client.get('/raises403/') response = self.client.get('/raises403/')
self.assertContains(response, 'test template', status_code=403) self.assertContains(response, 'test template', status_code=403)
finally:
restore_template_loaders()
def test_404(self): def test_404(self):
response = self.client.get('/raises404/') response = self.client.get('/raises404/')

View File

@ -1,8 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.test import TestCase from django.test import TestCase
from django.test.utils import (setup_test_template_loader, from django.test.utils import override_settings, override_with_test_loader
restore_template_loaders, override_settings)
from ..models import UrlArticle from ..models import UrlArticle
@ -41,17 +40,13 @@ class DefaultsTests(TestCase):
Test that 404.html and 500.html templates are picked by their respective Test that 404.html and 500.html templates are picked by their respective
handler. handler.
""" """
setup_test_template_loader( with override_with_test_loader({
{'404.html': 'This is a test template for a 404 error.', '404.html': 'This is a test template for a 404 error.',
'500.html': 'This is a test template for a 500 error.'} '500.html': 'This is a test template for a 500 error.'}):
)
try:
for code, url in ((404, '/non_existing_url/'), (500, '/server_error/')): for code, url in ((404, '/non_existing_url/'), (500, '/server_error/')):
response = self.client.get(url) response = self.client.get(url)
self.assertContains(response, "test template for a %d error" % code, self.assertContains(response, "test template for a %d error" % code,
status_code=code) status_code=code)
finally:
restore_template_loaders()
def test_get_absolute_url_attributes(self): def test_get_absolute_url_attributes(self):
"A model can set attributes on the get_absolute_url method" "A model can set attributes on the get_absolute_url method"