Skip to content

Commit

Permalink
Fixed #35622 -- Made unittest ignore Django assertions in traceback f…
Browse files Browse the repository at this point in the history
…rames.

Co-authored-by: Natalia <[email protected]>
  • Loading branch information
adamchainz and nessita committed Aug 9, 2024
1 parent e1606d2 commit 9582745
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 1 deletion.
3 changes: 3 additions & 0 deletions django/contrib/admin/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
from django.utils.deprecation import MiddlewareMixin
from django.utils.translation import gettext as _

# Make unittest ignore frames in this module when reporting failures.
__unittest = True


class CSPMiddleware(MiddlewareMixin):
"""The admin's JavaScript should be compatible with CSP."""
Expand Down
3 changes: 3 additions & 0 deletions django/contrib/messages/test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from .api import get_messages

# Make unittest ignore frames in this module when reporting failures.
__unittest = True


class MessagesTestMixin:
def assertMessages(self, response, expected_messages, *, ordered=True):
Expand Down
3 changes: 3 additions & 0 deletions django/test/testcases.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@
"skipUnlessDBFeature",
)

# Make unittest ignore frames in this module when reporting failures.
__unittest = True


if not PY311:
# Backport of unittest.case._enter_context() from Python 3.11.
Expand Down
4 changes: 3 additions & 1 deletion docs/releases/5.2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,9 @@ Templates
Tests
~~~~~

* ...
* Stack frames from Django's custom assertions are now hidden. This makes test
failures easier to read and enables :option:`test --pdb` to directly enter
into the failing test method.

URLs
~~~~
Expand Down
16 changes: 16 additions & 0 deletions tests/messages_tests/tests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import importlib
import sys
import traceback
import unittest
from unittest import mock

from django.conf import settings
Expand Down Expand Up @@ -185,3 +187,17 @@ def test_mismatching_length(self):
)
with self.assertRaisesMessage(AssertionError, msg):
self.assertMessages(response, [])

def test_method_frames_ignored_by_unittest(self):
response = FakeResponse()
try:
self.assertMessages(response, [object()])
except AssertionError:
exc_type, exc, tb = sys.exc_info()

result = unittest.TestResult()
result.addFailure(self, (exc_type, exc, tb))
stack = traceback.extract_tb(exc.__traceback__)
self.assertEqual(len(stack), 1)
# Top element in the stack is this method, not assertMessages.
self.assertEqual(stack[-1].name, "test_method_frames_ignored_by_unittest")
14 changes: 14 additions & 0 deletions tests/test_utils/tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import sys
import threading
import traceback
import unittest
import warnings
from io import StringIO
Expand Down Expand Up @@ -1113,6 +1114,19 @@ def test_not_equal_parsing_errors(self):
with self.assertRaises(AssertionError):
self.assertJSONNotEqual(valid_json, invalid_json)

def test_method_frames_ignored_by_unittest(self):
try:
self.assertJSONEqual("1", "2")
except AssertionError:
exc_type, exc, tb = sys.exc_info()

result = unittest.TestResult()
result.addFailure(self, (exc_type, exc, tb))
stack = traceback.extract_tb(exc.__traceback__)
self.assertEqual(len(stack), 1)
# Top element in the stack is this method, not assertJSONEqual.
self.assertEqual(stack[-1].name, "test_method_frames_ignored_by_unittest")


class XMLEqualTests(SimpleTestCase):
def test_simple_equal(self):
Expand Down

0 comments on commit 9582745

Please sign in to comment.