Fixed #33400 -- Added support for msg_prefix and count arguments to assertTemplateUsed()/assertTemplateNotUsed() used as context managers.

This commit is contained in:
Ad Timmering 2022-01-01 14:55:55 +09:00 committed by Mariusz Felisiak
parent e700a3714f
commit 806efe912b
2 changed files with 73 additions and 37 deletions

View File

@ -93,9 +93,12 @@ class _AssertNumQueriesContext(CaptureQueriesContext):
class _AssertTemplateUsedContext:
def __init__(self, test_case, template_name):
def __init__(self, test_case, template_name, msg_prefix='', count=None):
self.test_case = test_case
self.template_name = template_name
self.msg_prefix = msg_prefix
self.count = count
self.rendered_templates = []
self.rendered_template_names = []
self.context = ContextList()
@ -106,10 +109,10 @@ class _AssertTemplateUsedContext:
self.context.append(copy(context))
def test(self):
return self.template_name in self.rendered_template_names
def message(self):
return '%s was not rendered.' % self.template_name
self.test_case._assert_template_used(
self.template_name, self.rendered_template_names, self.msg_prefix,
self.count,
)
def __enter__(self):
template_rendered.connect(self.on_template_render)
@ -119,24 +122,16 @@ class _AssertTemplateUsedContext:
template_rendered.disconnect(self.on_template_render)
if exc_type is not None:
return
if not self.test():
message = self.message()
if self.rendered_templates:
message += ' Following templates were rendered: %s' % (
', '.join(self.rendered_template_names)
)
else:
message += ' No template was rendered.'
self.test_case.fail(message)
self.test()
class _AssertTemplateNotUsedContext(_AssertTemplateUsedContext):
def test(self):
return self.template_name not in self.rendered_template_names
def message(self):
return '%s was rendered.' % self.template_name
self.test_case.assertFalse(
self.template_name in self.rendered_template_names,
f"{self.msg_prefix}Template '{self.template_name}' was used "
f"unexpectedly in rendering the response"
)
class DatabaseOperationForbidden(AssertionError):
@ -646,18 +641,7 @@ class SimpleTestCase(unittest.TestCase):
template_names = [t.name for t in response.templates if t.name is not None]
return None, template_names, msg_prefix
def assertTemplateUsed(self, response=None, template_name=None, msg_prefix='', count=None):
"""
Assert that the template with the provided name was used in rendering
the response. Also usable as context manager.
"""
context_mgr_template, template_names, msg_prefix = self._get_template_used(
response, template_name, msg_prefix, 'assertTemplateUsed',
)
if context_mgr_template:
# Use assertTemplateUsed as context manager.
return _AssertTemplateUsedContext(self, context_mgr_template)
def _assert_template_used(self, template_name, template_names, msg_prefix, count):
if not template_names:
self.fail(msg_prefix + "No templates used to render the response")
self.assertTrue(
@ -675,6 +659,20 @@ class SimpleTestCase(unittest.TestCase):
% (template_name, count, template_names.count(template_name))
)
def assertTemplateUsed(self, response=None, template_name=None, msg_prefix='', count=None):
"""
Assert that the template with the provided name was used in rendering
the response. Also usable as context manager.
"""
context_mgr_template, template_names, msg_prefix = self._get_template_used(
response, template_name, msg_prefix, 'assertTemplateUsed',
)
if context_mgr_template:
# Use assertTemplateUsed as context manager.
return _AssertTemplateUsedContext(self, context_mgr_template, msg_prefix, count)
self._assert_template_used(template_name, template_names, msg_prefix, count)
def assertTemplateNotUsed(self, response=None, template_name=None, msg_prefix=''):
"""
Assert that the template with the provided name was NOT used in
@ -685,7 +683,7 @@ class SimpleTestCase(unittest.TestCase):
)
if context_mgr_template:
# Use assertTemplateNotUsed as context manager.
return _AssertTemplateNotUsedContext(self, context_mgr_template)
return _AssertTemplateNotUsedContext(self, context_mgr_template, msg_prefix)
self.assertFalse(
template_name in template_names,

View File

@ -508,7 +508,7 @@ class AssertTemplateUsedContextManagerTests(SimpleTestCase):
pass
def test_error_message(self):
msg = 'template_used/base.html was not rendered. No template was rendered.'
msg = 'No templates used to render the response'
with self.assertRaisesMessage(AssertionError, msg):
with self.assertTemplateUsed('template_used/base.html'):
pass
@ -518,8 +518,8 @@ class AssertTemplateUsedContextManagerTests(SimpleTestCase):
pass
msg2 = (
'template_used/base.html was not rendered. Following templates '
'were rendered: template_used/alternative.html'
"Template 'template_used/base.html' was not a template used to render "
"the response. Actual template(s) used: template_used/alternative.html"
)
with self.assertRaisesMessage(AssertionError, msg2):
with self.assertTemplateUsed('template_used/base.html'):
@ -529,6 +529,43 @@ class AssertTemplateUsedContextManagerTests(SimpleTestCase):
response = self.client.get('/test_utils/no_template_used/')
self.assertTemplateUsed(response, 'template_used/base.html')
def test_msg_prefix(self):
msg_prefix = 'Prefix'
msg = f'{msg_prefix}: No templates used to render the response'
with self.assertRaisesMessage(AssertionError, msg):
with self.assertTemplateUsed('template_used/base.html', msg_prefix=msg_prefix):
pass
with self.assertRaisesMessage(AssertionError, msg):
with self.assertTemplateUsed(
template_name='template_used/base.html',
msg_prefix=msg_prefix,
):
pass
msg = (
f"{msg_prefix}: Template 'template_used/base.html' was not a "
f"template used to render the response. Actual template(s) used: "
f"template_used/alternative.html"
)
with self.assertRaisesMessage(AssertionError, msg):
with self.assertTemplateUsed('template_used/base.html', msg_prefix=msg_prefix):
render_to_string('template_used/alternative.html')
def test_count(self):
with self.assertTemplateUsed('template_used/base.html', count=2):
render_to_string('template_used/base.html')
render_to_string('template_used/base.html')
msg = (
"Template 'template_used/base.html' was expected to be rendered "
"3 time(s) but was actually rendered 2 time(s)."
)
with self.assertRaisesMessage(AssertionError, msg):
with self.assertTemplateUsed('template_used/base.html', count=3):
render_to_string('template_used/base.html')
render_to_string('template_used/base.html')
def test_failure(self):
msg = 'response and/or template_name argument must be provided'
with self.assertRaisesMessage(TypeError, msg):
@ -549,8 +586,9 @@ class AssertTemplateUsedContextManagerTests(SimpleTestCase):
pass
msg = (
'template_used/base.html was not rendered. Following '
'templates were rendered: template_used/alternative.html'
"Template 'template_used/base.html' was not a template used to "
"render the response. Actual template(s) used: "
"template_used/alternative.html"
)
with self.assertRaisesMessage(AssertionError, msg):
with self.assertTemplateUsed('template_used/base.html'):