mirror of https://github.com/django/django.git
Fixed #34657 -- Made assert(Not)Contains/assertInHTML display haystacks in error messages.
This commit is contained in:
parent
54d9d26ebf
commit
1dae65dc63
|
@ -495,6 +495,7 @@ class SimpleTestCase(unittest.TestCase):
|
|||
content = b"".join(response.streaming_content)
|
||||
else:
|
||||
content = response.content
|
||||
content_repr = safe_repr(content)
|
||||
if not isinstance(text, bytes) or html:
|
||||
text = str(text)
|
||||
content = content.decode(response.charset)
|
||||
|
@ -509,7 +510,7 @@ class SimpleTestCase(unittest.TestCase):
|
|||
self, text, None, "Second argument is not valid HTML:"
|
||||
)
|
||||
real_count = content.count(text)
|
||||
return (text_repr, real_count, msg_prefix)
|
||||
return text_repr, real_count, msg_prefix, content_repr
|
||||
|
||||
def assertContains(
|
||||
self, response, text, count=None, status_code=200, msg_prefix="", html=False
|
||||
|
@ -521,7 +522,7 @@ class SimpleTestCase(unittest.TestCase):
|
|||
If ``count`` is None, the count doesn't matter - the assertion is true
|
||||
if the text occurs at least once in the response.
|
||||
"""
|
||||
text_repr, real_count, msg_prefix = self._assert_contains(
|
||||
text_repr, real_count, msg_prefix, content_repr = self._assert_contains(
|
||||
response, text, status_code, msg_prefix, html
|
||||
)
|
||||
|
||||
|
@ -529,13 +530,18 @@ class SimpleTestCase(unittest.TestCase):
|
|||
self.assertEqual(
|
||||
real_count,
|
||||
count,
|
||||
msg_prefix
|
||||
+ "Found %d instances of %s in response (expected %d)"
|
||||
% (real_count, text_repr, count),
|
||||
(
|
||||
f"{msg_prefix}Found {real_count} instances of {text_repr} "
|
||||
f"(expected {count}) in the following response\n{content_repr}"
|
||||
),
|
||||
)
|
||||
else:
|
||||
self.assertTrue(
|
||||
real_count != 0, msg_prefix + "Couldn't find %s in response" % text_repr
|
||||
real_count != 0,
|
||||
(
|
||||
f"{msg_prefix}Couldn't find {text_repr} in the following response\n"
|
||||
f"{content_repr}"
|
||||
),
|
||||
)
|
||||
|
||||
def assertNotContains(
|
||||
|
@ -546,12 +552,17 @@ class SimpleTestCase(unittest.TestCase):
|
|||
successfully, (i.e., the HTTP status code was as expected) and that
|
||||
``text`` doesn't occur in the content of the response.
|
||||
"""
|
||||
text_repr, real_count, msg_prefix = self._assert_contains(
|
||||
text_repr, real_count, msg_prefix, content_repr = self._assert_contains(
|
||||
response, text, status_code, msg_prefix, html
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
real_count, 0, msg_prefix + "Response should not contain %s" % text_repr
|
||||
real_count,
|
||||
0,
|
||||
(
|
||||
f"{msg_prefix}{text_repr} unexpectedly found in the following response"
|
||||
f"\n{content_repr}"
|
||||
),
|
||||
)
|
||||
|
||||
def _check_test_client_response(self, response, attribute, method_name):
|
||||
|
@ -884,17 +895,23 @@ class SimpleTestCase(unittest.TestCase):
|
|||
real_count = parsed_haystack.count(parsed_needle)
|
||||
if msg_prefix:
|
||||
msg_prefix += ": "
|
||||
haystack_repr = safe_repr(haystack)
|
||||
if count is not None:
|
||||
self.assertEqual(
|
||||
real_count,
|
||||
count,
|
||||
msg_prefix
|
||||
+ "Found %d instances of '%s' in response (expected %d)"
|
||||
% (real_count, needle, count),
|
||||
(
|
||||
f"{msg_prefix}Found {real_count} instances of {needle!r} (expected "
|
||||
f"{count}) in the following response\n{haystack_repr}"
|
||||
),
|
||||
)
|
||||
else:
|
||||
self.assertTrue(
|
||||
real_count != 0, msg_prefix + "Couldn't find '%s' in response" % needle
|
||||
real_count != 0,
|
||||
(
|
||||
f"{msg_prefix}Couldn't find {needle!r} in the following response\n"
|
||||
f"{haystack_repr}"
|
||||
),
|
||||
)
|
||||
|
||||
def assertJSONEqual(self, raw, expected_data, msg=None):
|
||||
|
|
|
@ -201,7 +201,10 @@ Templates
|
|||
Tests
|
||||
~~~~~
|
||||
|
||||
* ...
|
||||
* :meth:`~django.test.SimpleTestCase.assertContains`,
|
||||
:meth:`~django.test.SimpleTestCase.assertNotContains`, and
|
||||
:meth:`~django.test.SimpleTestCase.assertInHTML` assertions now add haystacks
|
||||
to assertion error messages.
|
||||
|
||||
URLs
|
||||
~~~~
|
||||
|
|
|
@ -1700,6 +1700,10 @@ your test suite.
|
|||
attribute ordering is not significant. See
|
||||
:meth:`~SimpleTestCase.assertHTMLEqual` for more details.
|
||||
|
||||
.. versionchanged:: 5.1
|
||||
|
||||
In older versions, error messages didn't contain the response content.
|
||||
|
||||
.. method:: SimpleTestCase.assertNotContains(response, text, status_code=200, msg_prefix='', html=False)
|
||||
|
||||
Asserts that a :class:`response <django.http.HttpResponse>` produced the
|
||||
|
@ -1712,6 +1716,10 @@ your test suite.
|
|||
attribute ordering is not significant. See
|
||||
:meth:`~SimpleTestCase.assertHTMLEqual` for more details.
|
||||
|
||||
.. versionchanged:: 5.1
|
||||
|
||||
In older versions, error messages didn't contain the response content.
|
||||
|
||||
.. method:: SimpleTestCase.assertTemplateUsed(response, template_name, msg_prefix='', count=None)
|
||||
|
||||
Asserts that the template with the given name was used in rendering the
|
||||
|
@ -1848,6 +1856,10 @@ your test suite.
|
|||
Whitespace in most cases is ignored, and attribute ordering is not
|
||||
significant. See :meth:`~SimpleTestCase.assertHTMLEqual` for more details.
|
||||
|
||||
.. versionchanged:: 5.1
|
||||
|
||||
In older versions, error messages didn't contain the ``haystack``.
|
||||
|
||||
.. method:: SimpleTestCase.assertJSONEqual(raw, expected_data, msg=None)
|
||||
|
||||
Asserts that the JSON fragments ``raw`` and ``expected_data`` are equal.
|
||||
|
|
|
@ -80,86 +80,141 @@ class AssertContainsTests(SimpleTestCase):
|
|||
try:
|
||||
self.assertNotContains(response, "once")
|
||||
except AssertionError as e:
|
||||
self.assertIn("Response should not contain 'once'", str(e))
|
||||
self.assertIn(
|
||||
"'once' unexpectedly found in the following response\n"
|
||||
f"{response.content}",
|
||||
str(e),
|
||||
)
|
||||
try:
|
||||
self.assertNotContains(response, "once", msg_prefix="abc")
|
||||
except AssertionError as e:
|
||||
self.assertIn("abc: Response should not contain 'once'", str(e))
|
||||
self.assertIn(
|
||||
"abc: 'once' unexpectedly found in the following response\n"
|
||||
f"{response.content}",
|
||||
str(e),
|
||||
)
|
||||
|
||||
try:
|
||||
self.assertContains(response, "never", 1)
|
||||
except AssertionError as e:
|
||||
self.assertIn(
|
||||
"Found 0 instances of 'never' in response (expected 1)", str(e)
|
||||
"Found 0 instances of 'never' (expected 1) in the following response\n"
|
||||
f"{response.content}",
|
||||
str(e),
|
||||
)
|
||||
try:
|
||||
self.assertContains(response, "never", 1, msg_prefix="abc")
|
||||
except AssertionError as e:
|
||||
self.assertIn(
|
||||
"abc: Found 0 instances of 'never' in response (expected 1)", str(e)
|
||||
"abc: Found 0 instances of 'never' (expected 1) in the following "
|
||||
f"response\n{response.content}",
|
||||
str(e),
|
||||
)
|
||||
|
||||
try:
|
||||
self.assertContains(response, "once", 0)
|
||||
except AssertionError as e:
|
||||
self.assertIn(
|
||||
"Found 1 instances of 'once' in response (expected 0)", str(e)
|
||||
"Found 1 instances of 'once' (expected 0) in the following response\n"
|
||||
f"{response.content}",
|
||||
str(e),
|
||||
)
|
||||
try:
|
||||
self.assertContains(response, "once", 0, msg_prefix="abc")
|
||||
except AssertionError as e:
|
||||
self.assertIn(
|
||||
"abc: Found 1 instances of 'once' in response (expected 0)", str(e)
|
||||
"abc: Found 1 instances of 'once' (expected 0) in the following "
|
||||
f"response\n{response.content}",
|
||||
str(e),
|
||||
)
|
||||
|
||||
try:
|
||||
self.assertContains(response, "once", 2)
|
||||
except AssertionError as e:
|
||||
self.assertIn(
|
||||
"Found 1 instances of 'once' in response (expected 2)", str(e)
|
||||
"Found 1 instances of 'once' (expected 2) in the following response\n"
|
||||
f"{response.content}",
|
||||
str(e),
|
||||
)
|
||||
try:
|
||||
self.assertContains(response, "once", 2, msg_prefix="abc")
|
||||
except AssertionError as e:
|
||||
self.assertIn(
|
||||
"abc: Found 1 instances of 'once' in response (expected 2)", str(e)
|
||||
"abc: Found 1 instances of 'once' (expected 2) in the following "
|
||||
f"response\n{response.content}",
|
||||
str(e),
|
||||
)
|
||||
|
||||
try:
|
||||
self.assertContains(response, "twice", 1)
|
||||
except AssertionError as e:
|
||||
self.assertIn(
|
||||
"Found 2 instances of 'twice' in response (expected 1)", str(e)
|
||||
"Found 2 instances of 'twice' (expected 1) in the following response\n"
|
||||
f"{response.content}",
|
||||
str(e),
|
||||
)
|
||||
try:
|
||||
self.assertContains(response, "twice", 1, msg_prefix="abc")
|
||||
except AssertionError as e:
|
||||
self.assertIn(
|
||||
"abc: Found 2 instances of 'twice' in response (expected 1)", str(e)
|
||||
"abc: Found 2 instances of 'twice' (expected 1) in the following "
|
||||
f"response\n{response.content}",
|
||||
str(e),
|
||||
)
|
||||
|
||||
try:
|
||||
self.assertContains(response, "thrice")
|
||||
except AssertionError as e:
|
||||
self.assertIn("Couldn't find 'thrice' in response", str(e))
|
||||
self.assertIn(
|
||||
f"Couldn't find 'thrice' in the following response\n{response.content}",
|
||||
str(e),
|
||||
)
|
||||
try:
|
||||
self.assertContains(response, "thrice", msg_prefix="abc")
|
||||
except AssertionError as e:
|
||||
self.assertIn("abc: Couldn't find 'thrice' in response", str(e))
|
||||
self.assertIn(
|
||||
"abc: Couldn't find 'thrice' in the following response\n"
|
||||
f"{response.content}",
|
||||
str(e),
|
||||
)
|
||||
|
||||
try:
|
||||
self.assertContains(response, "thrice", 3)
|
||||
except AssertionError as e:
|
||||
self.assertIn(
|
||||
"Found 0 instances of 'thrice' in response (expected 3)", str(e)
|
||||
"Found 0 instances of 'thrice' (expected 3) in the following response\n"
|
||||
f"{response.content}",
|
||||
str(e),
|
||||
)
|
||||
try:
|
||||
self.assertContains(response, "thrice", 3, msg_prefix="abc")
|
||||
except AssertionError as e:
|
||||
self.assertIn(
|
||||
"abc: Found 0 instances of 'thrice' in response (expected 3)", str(e)
|
||||
"abc: Found 0 instances of 'thrice' (expected 3) in the following "
|
||||
f"response\n{response.content}",
|
||||
str(e),
|
||||
)
|
||||
|
||||
long_content = (
|
||||
b"This is a very very very very very very very very long message which "
|
||||
b"exceedes the max limit of truncation."
|
||||
)
|
||||
response = HttpResponse(long_content)
|
||||
msg = f"Couldn't find 'thrice' in the following response\n{long_content}"
|
||||
with self.assertRaisesMessage(AssertionError, msg):
|
||||
self.assertContains(response, "thrice")
|
||||
|
||||
msg = (
|
||||
"Found 1 instances of 'This' (expected 3) in the following response\n"
|
||||
f"{long_content}"
|
||||
)
|
||||
with self.assertRaisesMessage(AssertionError, msg):
|
||||
self.assertContains(response, "This", 3)
|
||||
|
||||
msg = f"'very' unexpectedly found in the following response\n{long_content}"
|
||||
with self.assertRaisesMessage(AssertionError, msg):
|
||||
self.assertNotContains(response, "very")
|
||||
|
||||
def test_unicode_contains(self):
|
||||
"Unicode characters can be found in template context"
|
||||
# Regression test for #10183
|
||||
|
|
|
@ -985,12 +985,18 @@ class HTMLEqualTests(SimpleTestCase):
|
|||
|
||||
class InHTMLTests(SimpleTestCase):
|
||||
def test_needle_msg(self):
|
||||
msg = "False is not true : Couldn't find '<b>Hello</b>' in response"
|
||||
msg = (
|
||||
"False is not true : Couldn't find '<b>Hello</b>' in the following "
|
||||
"response\n'<p>Test</p>'"
|
||||
)
|
||||
with self.assertRaisesMessage(AssertionError, msg):
|
||||
self.assertInHTML("<b>Hello</b>", "<p>Test</p>")
|
||||
|
||||
def test_msg_prefix(self):
|
||||
msg = "False is not true : Prefix: Couldn't find '<b>Hello</b>' in response"
|
||||
msg = (
|
||||
"False is not true : Prefix: Couldn't find '<b>Hello</b>' in the following "
|
||||
'response\n\'<input type="text" name="Hello" />\''
|
||||
)
|
||||
with self.assertRaisesMessage(AssertionError, msg):
|
||||
self.assertInHTML(
|
||||
"<b>Hello</b>",
|
||||
|
@ -1000,8 +1006,9 @@ class InHTMLTests(SimpleTestCase):
|
|||
|
||||
def test_count_msg_prefix(self):
|
||||
msg = (
|
||||
"2 != 1 : Prefix: Found 2 instances of '<b>Hello</b>' in response "
|
||||
"(expected 1)"
|
||||
"2 != 1 : Prefix: Found 2 instances of '<b>Hello</b>' (expected 1) in the "
|
||||
"following response\n'<b>Hello</b><b>Hello</b>'"
|
||||
""
|
||||
)
|
||||
with self.assertRaisesMessage(AssertionError, msg):
|
||||
self.assertInHTML(
|
||||
|
@ -1011,6 +1018,38 @@ class InHTMLTests(SimpleTestCase):
|
|||
msg_prefix="Prefix",
|
||||
)
|
||||
|
||||
def test_base(self):
|
||||
haystack = "<p><b>Hello</b> <span>there</span>! Hi <span>there</span>!</p>"
|
||||
|
||||
self.assertInHTML("<b>Hello</b>", haystack=haystack)
|
||||
msg = f"Couldn't find '<p>Howdy</p>' in the following response\n{haystack!r}"
|
||||
with self.assertRaisesMessage(AssertionError, msg):
|
||||
self.assertInHTML("<p>Howdy</p>", haystack)
|
||||
|
||||
self.assertInHTML("<span>there</span>", haystack=haystack, count=2)
|
||||
msg = (
|
||||
"Found 1 instances of '<b>Hello</b>' (expected 2) in the following response"
|
||||
f"\n{haystack!r}"
|
||||
)
|
||||
with self.assertRaisesMessage(AssertionError, msg):
|
||||
self.assertInHTML("<b>Hello</b>", haystack=haystack, count=2)
|
||||
|
||||
def test_long_haystack(self):
|
||||
haystack = (
|
||||
"<p>This is a very very very very very very very very long message which "
|
||||
"exceedes the max limit of truncation.</p>"
|
||||
)
|
||||
msg = f"Couldn't find '<b>Hello</b>' in the following response\n{haystack!r}"
|
||||
with self.assertRaisesMessage(AssertionError, msg):
|
||||
self.assertInHTML("<b>Hello</b>", haystack)
|
||||
|
||||
msg = (
|
||||
"Found 0 instances of '<b>This</b>' (expected 3) in the following response"
|
||||
f"\n{haystack!r}"
|
||||
)
|
||||
with self.assertRaisesMessage(AssertionError, msg):
|
||||
self.assertInHTML("<b>This</b>", haystack, 3)
|
||||
|
||||
|
||||
class JSONEqualTests(SimpleTestCase):
|
||||
def test_simple_equal(self):
|
||||
|
|
Loading…
Reference in New Issue