New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
unittest swallows part of stack trace when raising AssertionError in a TestCase #69147
Comments
unittest swallows some lines of the stack trace when raising an AssertionError using the "raise from" syntax inside a TestCase. This marks it harder to pinpoint the source of test failures. It is also confusing to see a stack trace like this because the error doesn't originate where the stack trace says it originates. To reproduce: import unittest
def foo():
raise Exception("foo")
class Test(unittest.TestCase):
def test_not_okay(self):
try:
foo()
except Exception as exc:
raise AssertionError("bar") from exc
def test_okay1(self):
try:
foo()
except Exception as exc:
raise ValueError("bar") from exc
def test_okay2(self):
try:
foo()
except Exception as exc:
raise Exception("bar") from exc The result (observe how the display for "test_not_okay" differs from the other two):
Traceback (most recent call last):
File "/Users/chris/dev/error.py", line 17, in test_okay1
foo()
File "/Users/chris/dev/error.py", line 5, in foo
raise Exception("foo")
Exception: foo
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/chris/dev/error.py", line 19, in test_okay1
raise ValueError("bar") from exc
ValueError: bar
Traceback (most recent call last):
File "/Users/chris/dev/error.py", line 23, in test_okay2
foo()
File "/Users/chris/dev/error.py", line 5, in foo
raise Exception("foo")
Exception: foo
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/chris/dev/error.py", line 25, in test_okay2
raise Exception("bar") from exc
Exception: bar
Traceback (most recent call last):
File "/Users/chris/dev/error.py", line 11, in test_not_okay
foo()
Exception: foo
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/chris/dev/error.py", line 13, in test_not_okay
raise AssertionError("bar") from exc
AssertionError: bar
|
I guess this isn't limited just to the "raise from" syntax. It also occurs if "from exc" is removed from the example above. |
Hmm, this is a little surprising, but - why are you raising AssertionError like that - thats what assertRaises is for. |
This is simply a reduced test case to illustrate the issue more clearly. There was more to it in how I was using it in practice. |
I'm fairly sure its eating the stack frames because the calling frames are annotated __unittest__ - its technically a feature :/. |
Yes, it is... ish. The frame skipping code occurs when we serialise exceptions, and we pass a limit in. The limit is calculated on the main exception only. If the cause has a longer exception than the limit we calculated, you'd see this behaviour. Probably need to make it possible to do per-exception processing of limit: I think via a callback or similar mechanism in traceback (because the cause might have thrown from some code that is also marked __unittest, so if we're honouring that, we should honour it within each exception. |
I've run into this bug too. Took a while to track down the cause :) |
I think this is the same as bpo-42247, where I've recently attached a patch that removes __unittest frames from the traceback rather than count them and then set a limit for printing. I could add to that patch what Robert suggests here - to filter the __cause__ traceback as well. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: