Opened 10 years ago

Closed 9 years ago

#23300 closed Bug (fixed)

TestCase.assertTemplateUsed passes erroneously on an HttpResponse

Reported by: zags Owned by: Davide Ceretti
Component: Testing framework Version: dev
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

Description

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 by zags, 10 years ago

Summary: TestCase.assertTemplateUsed passes erroniously on an HttpResponseTestCase.assertTemplateUsed passes erroneously on an HttpResponse

comment:2 by Baptiste Mispelon, 10 years ago

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

Hi,

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)
    503503
    504504    def _assert_template_used(self, response, template_name, msg_prefix):
    505 
    506505        if response is None and template_name is None:
    507506            raise TypeError('response and/or template_name argument must be provided')
    508507
     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)
     510
    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 by Davide Ceretti, 10 years ago

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

comment:4 by Loic Bistuer, 10 years ago

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

Version 0, edited 10 years ago by Loic Bistuer (next)

comment:5 by Tim Graham <timograham@…>, 9 years ago

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