Opened 7 years ago

Closed 6 years ago

Last modified 4 years ago

#10183 closed (fixed)

assertContains fails when there is unicode in the response content

Reported by: drakonen Owned by: nobody
Component: Testing framework Version: 1.0
Severity: Keywords: testcases, assertContains, assertNotContains
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

# views.py
#

from django.shortcuts import render_to_response

def index(request):
    return render_to_response('index.html')

#
# index.html

aaäaa

#
# tests.py

from django.test import TestCase

class TestViews(TestCase):
    def test_index(self):
        response = self.client.get('/')
        self.assertContains(response, u'aa')


#
# results in:

======================================================================
ERROR: test_index (stuff.tests.TestViews)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/johan/devel/tester/stuff/tests.py", line 6, in test_index
    self.assertContains(response, u'aa')
  File "/usr/lib/python2.5/site-packages/django/test/testcases.py", line 267, in assertContains
    real_count = response.content.count(text)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2: ordinal not in range(128)

----------------------------------------------------------------------

Attachments (5)

assertContainsPatch.diff (1.5 KB) - added by drakonen 7 years ago.
django.test.testcases_assertContainsPatch.2.diff (1.6 KB) - added by trbs 6 years ago.
10183-cant-reproduce.diff (3.4 KB) - added by ericholscher 6 years ago.
Patch of the test case I made that couldn't reproduce the above.
10183-assertcontains-unicode-testcase.diff (2.8 KB) - added by trbs 6 years ago.
10183-django.test.testcases_assertContainsPatch.3.diff (1.5 KB) - added by trbs 6 years ago.

Download all attachments as: .zip

Change History (14)

Changed 7 years ago by drakonen

comment:1 Changed 6 years ago by trbs

  • Keywords testcases assertContains assertNotContains added
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

A little rational behind the patch;

Python raised the UnicodeDecodeError because it's asked to count a unicode string within a non-unicode string.
HttpResponse's content property uses smart_str to create content data, it would seem to make sense to do
the same for any text used in assertContains and assertNotContains.

I've added an updated patch to this ticket which uses smart_str(text, response._charset) which matches the HttpResponse
object behavior. Could also have used settings.DEFAULT_CHARSET but it seems with ticket #10190 this might change later on so response._charset seems a safer bet :)

comment:2 Changed 6 years ago by anonymous

  • milestone post-1.0 deleted

Milestone post-1.0 deleted

comment:3 Changed 6 years ago by ericholscher

  • Triage Stage changed from Unreviewed to Accepted

This makes sense. Having the tests mimick what normal Django does is probably a good idea.

comment:4 Changed 6 years ago by claudep

Been confronted to this today. What prevents this to be included in 1.1 ?

comment:5 Changed 6 years ago by jacob

  • milestone set to 1.1

Changed 6 years ago by ericholscher

Patch of the test case I made that couldn't reproduce the above.

comment:6 Changed 6 years ago by ericholscher

  • Resolution set to invalid
  • Status changed from new to closed

I couldn't reproduce this. I have attached a test case to Django that passes. If you can make one that fails, please attach it to the case and reopen the ticket.

comment:7 Changed 6 years ago by trbs

  • Resolution invalid deleted
  • Status changed from closed to reopened

The reason the test case did not fail was because the assertion is not unicode.

I've attached a test case that does fail, it uses some Japanese in the template and tries to match a Unicode string in assertContains. Also attached a slight improvement on the patch for testcases.py because before a failed assertion did not use the smart_str version of the text resulting in "AssertionError: <unprintable AssertionError object>"

With the new test case it fails as follows:

======================================================================
ERROR: test_unicode_contains (regressiontests.test_client_regress.models.AssertContainsTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/trbs/django/trunk/tests/regressiontests/test_client_regress/models.py", line 71, in test_unicode_contains
    self.assertContains(r, '\xe5\xb3\xa0'.decode('utf-8'))
  File "/home/trbs/django/trunk/django/test/testcases.py", line 333, in assertContains
    real_count = response.content.count(text)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 2: ordinal not in range(128)

----------------------------------------------------------------------
Ran 48 tests in 4.005s

FAILED (errors=1)
Destroying test database...

Hope this clears things up, otherwise you can also drop me a line on irc :)

comment:8 Changed 6 years ago by russellm

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

(In [10415]) [1.0.X] Fixed #10183 -- Corrected the handling of unicode in assertContains and assertNotContains. Thanks to trbs for the patch.

Merge of r10414 from trunk.

comment:9 Changed 4 years ago by jacob

  • milestone 1.1 deleted

Milestone 1.1 deleted

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