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)
|
content = b"".join(response.streaming_content)
|
||||||
else:
|
else:
|
||||||
content = response.content
|
content = response.content
|
||||||
|
content_repr = safe_repr(content)
|
||||||
if not isinstance(text, bytes) or html:
|
if not isinstance(text, bytes) or html:
|
||||||
text = str(text)
|
text = str(text)
|
||||||
content = content.decode(response.charset)
|
content = content.decode(response.charset)
|
||||||
|
@ -509,7 +510,7 @@ class SimpleTestCase(unittest.TestCase):
|
||||||
self, text, None, "Second argument is not valid HTML:"
|
self, text, None, "Second argument is not valid HTML:"
|
||||||
)
|
)
|
||||||
real_count = content.count(text)
|
real_count = content.count(text)
|
||||||
return (text_repr, real_count, msg_prefix)
|
return text_repr, real_count, msg_prefix, content_repr
|
||||||
|
|
||||||
def assertContains(
|
def assertContains(
|
||||||
self, response, text, count=None, status_code=200, msg_prefix="", html=False
|
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 ``count`` is None, the count doesn't matter - the assertion is true
|
||||||
if the text occurs at least once in the response.
|
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
|
response, text, status_code, msg_prefix, html
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -529,13 +530,18 @@ class SimpleTestCase(unittest.TestCase):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
real_count,
|
real_count,
|
||||||
count,
|
count,
|
||||||
msg_prefix
|
(
|
||||||
+ "Found %d instances of %s in response (expected %d)"
|
f"{msg_prefix}Found {real_count} instances of {text_repr} "
|
||||||
% (real_count, text_repr, count),
|
f"(expected {count}) in the following response\n{content_repr}"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.assertTrue(
|
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(
|
def assertNotContains(
|
||||||
|
@ -546,12 +552,17 @@ class SimpleTestCase(unittest.TestCase):
|
||||||
successfully, (i.e., the HTTP status code was as expected) and that
|
successfully, (i.e., the HTTP status code was as expected) and that
|
||||||
``text`` doesn't occur in the content of the response.
|
``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
|
response, text, status_code, msg_prefix, html
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
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):
|
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)
|
real_count = parsed_haystack.count(parsed_needle)
|
||||||
if msg_prefix:
|
if msg_prefix:
|
||||||
msg_prefix += ": "
|
msg_prefix += ": "
|
||||||
|
haystack_repr = safe_repr(haystack)
|
||||||
if count is not None:
|
if count is not None:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
real_count,
|
real_count,
|
||||||
count,
|
count,
|
||||||
msg_prefix
|
(
|
||||||
+ "Found %d instances of '%s' in response (expected %d)"
|
f"{msg_prefix}Found {real_count} instances of {needle!r} (expected "
|
||||||
% (real_count, needle, count),
|
f"{count}) in the following response\n{haystack_repr}"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.assertTrue(
|
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):
|
def assertJSONEqual(self, raw, expected_data, msg=None):
|
||||||
|
|
|
@ -201,7 +201,10 @@ Templates
|
||||||
Tests
|
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
|
URLs
|
||||||
~~~~
|
~~~~
|
||||||
|
|
|
@ -1700,6 +1700,10 @@ your test suite.
|
||||||
attribute ordering is not significant. See
|
attribute ordering is not significant. See
|
||||||
:meth:`~SimpleTestCase.assertHTMLEqual` for more details.
|
: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)
|
.. method:: SimpleTestCase.assertNotContains(response, text, status_code=200, msg_prefix='', html=False)
|
||||||
|
|
||||||
Asserts that a :class:`response <django.http.HttpResponse>` produced the
|
Asserts that a :class:`response <django.http.HttpResponse>` produced the
|
||||||
|
@ -1712,6 +1716,10 @@ your test suite.
|
||||||
attribute ordering is not significant. See
|
attribute ordering is not significant. See
|
||||||
:meth:`~SimpleTestCase.assertHTMLEqual` for more details.
|
: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)
|
.. method:: SimpleTestCase.assertTemplateUsed(response, template_name, msg_prefix='', count=None)
|
||||||
|
|
||||||
Asserts that the template with the given name was used in rendering the
|
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
|
Whitespace in most cases is ignored, and attribute ordering is not
|
||||||
significant. See :meth:`~SimpleTestCase.assertHTMLEqual` for more details.
|
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)
|
.. method:: SimpleTestCase.assertJSONEqual(raw, expected_data, msg=None)
|
||||||
|
|
||||||
Asserts that the JSON fragments ``raw`` and ``expected_data`` are equal.
|
Asserts that the JSON fragments ``raw`` and ``expected_data`` are equal.
|
||||||
|
|
|
@ -80,86 +80,141 @@ class AssertContainsTests(SimpleTestCase):
|
||||||
try:
|
try:
|
||||||
self.assertNotContains(response, "once")
|
self.assertNotContains(response, "once")
|
||||||
except AssertionError as e:
|
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:
|
try:
|
||||||
self.assertNotContains(response, "once", msg_prefix="abc")
|
self.assertNotContains(response, "once", msg_prefix="abc")
|
||||||
except AssertionError as e:
|
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:
|
try:
|
||||||
self.assertContains(response, "never", 1)
|
self.assertContains(response, "never", 1)
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
self.assertIn(
|
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:
|
try:
|
||||||
self.assertContains(response, "never", 1, msg_prefix="abc")
|
self.assertContains(response, "never", 1, msg_prefix="abc")
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
self.assertIn(
|
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:
|
try:
|
||||||
self.assertContains(response, "once", 0)
|
self.assertContains(response, "once", 0)
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
self.assertIn(
|
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:
|
try:
|
||||||
self.assertContains(response, "once", 0, msg_prefix="abc")
|
self.assertContains(response, "once", 0, msg_prefix="abc")
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
self.assertIn(
|
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:
|
try:
|
||||||
self.assertContains(response, "once", 2)
|
self.assertContains(response, "once", 2)
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
self.assertIn(
|
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:
|
try:
|
||||||
self.assertContains(response, "once", 2, msg_prefix="abc")
|
self.assertContains(response, "once", 2, msg_prefix="abc")
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
self.assertIn(
|
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:
|
try:
|
||||||
self.assertContains(response, "twice", 1)
|
self.assertContains(response, "twice", 1)
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
self.assertIn(
|
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:
|
try:
|
||||||
self.assertContains(response, "twice", 1, msg_prefix="abc")
|
self.assertContains(response, "twice", 1, msg_prefix="abc")
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
self.assertIn(
|
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:
|
try:
|
||||||
self.assertContains(response, "thrice")
|
self.assertContains(response, "thrice")
|
||||||
except AssertionError as e:
|
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:
|
try:
|
||||||
self.assertContains(response, "thrice", msg_prefix="abc")
|
self.assertContains(response, "thrice", msg_prefix="abc")
|
||||||
except AssertionError as e:
|
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:
|
try:
|
||||||
self.assertContains(response, "thrice", 3)
|
self.assertContains(response, "thrice", 3)
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
self.assertIn(
|
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:
|
try:
|
||||||
self.assertContains(response, "thrice", 3, msg_prefix="abc")
|
self.assertContains(response, "thrice", 3, msg_prefix="abc")
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
self.assertIn(
|
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):
|
def test_unicode_contains(self):
|
||||||
"Unicode characters can be found in template context"
|
"Unicode characters can be found in template context"
|
||||||
# Regression test for #10183
|
# Regression test for #10183
|
||||||
|
|
|
@ -985,12 +985,18 @@ class HTMLEqualTests(SimpleTestCase):
|
||||||
|
|
||||||
class InHTMLTests(SimpleTestCase):
|
class InHTMLTests(SimpleTestCase):
|
||||||
def test_needle_msg(self):
|
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):
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
self.assertInHTML("<b>Hello</b>", "<p>Test</p>")
|
self.assertInHTML("<b>Hello</b>", "<p>Test</p>")
|
||||||
|
|
||||||
def test_msg_prefix(self):
|
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):
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
"<b>Hello</b>",
|
"<b>Hello</b>",
|
||||||
|
@ -1000,8 +1006,9 @@ class InHTMLTests(SimpleTestCase):
|
||||||
|
|
||||||
def test_count_msg_prefix(self):
|
def test_count_msg_prefix(self):
|
||||||
msg = (
|
msg = (
|
||||||
"2 != 1 : Prefix: Found 2 instances of '<b>Hello</b>' in response "
|
"2 != 1 : Prefix: Found 2 instances of '<b>Hello</b>' (expected 1) in the "
|
||||||
"(expected 1)"
|
"following response\n'<b>Hello</b><b>Hello</b>'"
|
||||||
|
""
|
||||||
)
|
)
|
||||||
with self.assertRaisesMessage(AssertionError, msg):
|
with self.assertRaisesMessage(AssertionError, msg):
|
||||||
self.assertInHTML(
|
self.assertInHTML(
|
||||||
|
@ -1011,6 +1018,38 @@ class InHTMLTests(SimpleTestCase):
|
||||||
msg_prefix="Prefix",
|
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):
|
class JSONEqualTests(SimpleTestCase):
|
||||||
def test_simple_equal(self):
|
def test_simple_equal(self):
|
||||||
|
|
Loading…
Reference in New Issue