#35622 closed Cleanup/optimization (fixed)
Make unittest ignore Django frames in tracebacks
Reported by: | Adam Johnson | Owned by: | Adam Johnson |
---|---|---|---|
Component: | Testing framework | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Make unittest ignore Django frames in tracebacks
The module containing Django’s custom assert methods (django.test.testcases
) does not have the __unittest
attribute. This makes unit test unnecessarily display frames in those methods when tests fail, and opens the debugger there when using --pdb
.
unittest ignores stack frames in modules with __unittest
defined (source, example). If add this in django.test.testcases
, we get the same behaviour.
Take these two failing tests:
from django.test import SimpleTestCase class ExampleTests(SimpleTestCase): def test_1_unittest_assert(self): x = 0 self.assertTrue(x) def test_2_django_assert(self): y = "[]" self.assertJSONEqual("{}", y)
Running them gives:
./manage.py test Found 2 test(s). System check identified no issues (0 silenced). FF ====================================================================== FAIL: test_1_unittest_assert (example.tests.ExampleTests.test_1_unittest_assert) ---------------------------------------------------------------------- Traceback (most recent call last): File "/.../example/tests.py", line 7, in test_1_unittest_assert self.assertTrue(x) AssertionError: 0 is not true ====================================================================== FAIL: test_2_django_assert (example.tests.ExampleTests.test_2_django_assert) ---------------------------------------------------------------------- Traceback (most recent call last): File "/.../example/tests.py", line 11, in test_2_django_assert self.assertJSONEqual("{}", y) File "/.../django/test/testcases.py", line 1020, in assertJSONEqual self.assertEqual(data, expected_data, msg=msg) AssertionError: {} != [] ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (failures=2)
Notice how the only frame shown for test_1_unittest_assert
is in the test itself, whilst test_2_django_assert
contains the frame from within Django. This is useless noise for the user, which is why unittest hides its own frames
Also, when running tests with --pdb
, pdb opens within the test for test_1_unittest_assert
.
We can run x
to check the value of variable x
and c
to continue:
$ ./manage.py test --pdb Found 2 test(s). System check identified no issues (0 silenced). F Opening PDB: AssertionError('0 is not true') > /.../example/tests.py(7)test_1_unittest_assert() -> self.assertTrue(x) (Pdb) x 0 (Pdb) c
But in test_2_django_assert
, pdb opens within the assertJSONEqual
method.
We need to run u
(up
) to traverse the stack to the test method before we can do any meaningful debugging.
(Some assert methods require multiple u
commands.)
F Opening PDB: AssertionError('{} != []') > /.../django/test/testcases.py(1020)assertJSONEqual() -> self.assertEqual(data, expected_data, msg=msg) (Pdb) u > /.../example/tests.py(11)test_2_django_assert() -> self.assertJSONEqual("{}", y) (Pdb) y '[]' (Pdb) c
Change History (5)
comment:1 by , 4 months ago
Has patch: | set |
---|---|
Owner: | set to |
Status: | new → assigned |
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 4 months ago
Patch needs improvement: | set |
---|
comment:3 by , 4 months ago
Patch needs improvement: | unset |
---|
comment:5 by , 4 months ago
Triage Stage: | Accepted → Ready for checkin |
---|
Thank you Adam for this ticket!
I agree with your analysis. For posterity, the referenced implementation looks like this: