Opened 2 years ago

Closed 2 years ago

#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 2 years ago by zags

Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset
Summary: TestCase.assertTemplateUsed passes erroniously on an HttpResponseTestCase.assertTemplateUsed passes erroneously on an HttpResponse

comment:2 Changed 2 years ago by Baptiste Mispelon

Needs documentation: set
Needs tests: set
Patch needs improvement: set
Triage Stage: UnreviewedAccepted


You can find the documentation for assertTemplateused at

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/

    diff --git a/django/test/ b/django/test/
    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 2 years ago by Davide Ceretti

Owner: changed from nobody to Davide Ceretti
Status: newassigned
Version: 1.6master

comment:4 Changed 2 years ago by Loic Bistuer

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

Last edited 2 years ago by Tim Graham (previous) (diff)

comment:5 Changed 2 years ago by Tim Graham <timograham@…>

Resolution: fixed
Status: assignedclosed

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