#23300 closed Bug (fixed)

TestCase.assertTemplateUsed passes erroneously on an HttpResponse

Reported by: zags Owned by: davide-ceretti
Component: Testing framework Version: master
Severity: Normal Keywords: asserttemplateused template
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: yes
Needs tests: yes Patch needs improvement: yes
Easy pickings: no UI/UX: no


The following test should fail. It is asserting that the response both renders and does not render the template "xxx.html", which is a contradiction. However, this test passes.

from django.test import TestCase
from django.http.response import HttpResponse

class TestTemplateUsed(TestCase):
    def test_template_used(self):
        response = HttpResponse("xxx")
        self.assertTemplateUsed(response, "xxx.html")
        self.assertTemplateNotUsed(response, "xxx.html")

The issue is that HttpResponse objects have no "template" attribute, which assertTemplateUsed interprets as an intention to use a context manager rather than an assertion.

def assertTemplateUsed(self, response=None, template_name=None, msg_prefix=''):
    if not hasattr(response, 'templates') or (response is None and template_name):

I'm not sure why this is implemented this way, but from the docs (I can only find the 1.5 docs of this feature; I'm not sure where the relevant docs are for 1.6 and later), it seems far more sensible to implement this as:

def assertTemplateUsed(self, response=None, template_name=None, msg_prefix=''):
    if (response is None and template_name):

Just to call out an important point, unless I am missing something, this feature is entirely undocumented in v1.6 and v1.7

Change History (5)

comment:1 Changed 22 months ago by zags

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Summary changed from TestCase.assertTemplateUsed passes erroniously on an HttpResponse to TestCase.assertTemplateUsed passes erroneously on an HttpResponse

comment:2 Changed 22 months ago by bmispelon

  • Needs documentation set
  • Needs tests set
  • Patch needs improvement set
  • Triage Stage changed from Unreviewed to Accepted


You can find the documentation for assertTemplateused at https://docs.djangoproject.com/en/dev/topics/testing/tools/#django.test.SimpleTestCase.assertTemplateUsed.

I looked into the issue a little bit and I agree with your analysis.
As a fix, I would suggest raising an exception when trying to use assertTemplateUsed (or assertTemplateNotUsed) on a response object that doesn't have any templates attributes.
Here's a simple patch that should apply cleanly on master:

  • django/test/testcases.py

    diff --git a/django/test/testcases.py b/django/test/testcases.py
    index d46f672..6f7ab71 100644
    a b class SimpleTestCase(unittest.TestCase): 
    502502                      "the response" % formset)
    504504    def _assert_template_used(self, response, template_name, msg_prefix):
    506505        if response is None and template_name is None:
    507506            raise TypeError('response and/or template_name argument must be provided')
     508        if template_name is not None and response is not None and not hasattr(response, 'templates'):
     509            raise ValueError("Response object %r has no attribute 'templates'." % response)
    509511        if msg_prefix:
    510512            msg_prefix += ": "

With this fix, your example now raises an exception and Django's test suite still passes.

comment:3 Changed 20 months ago by davide-ceretti

  • Owner changed from nobody to davide-ceretti
  • Status changed from new to assigned
  • Version changed from 1.6 to master

comment:4 Changed 19 months ago by loic

It's worth noting that response.templates is a monkey-patch from the Client; assertTemplateUsed won't work in any other context.

Last edited 19 months ago by timgraham (previous) (diff)

comment:5 Changed 19 months ago by Tim Graham <timograham@…>

  • Resolution set to fixed
  • Status changed from assigned to closed

In 2d06e3155a13e3ca9e63b97c7c9499a1e1ffd654:

Fixed #23300 -- Made assertTemplateUsed throw an error on responses not fetched using the test client.

Thanks zags for the report and bmispelon for the patch.

Note: See TracTickets for help on using tickets.
Back to Top