-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
What's the problem this feature will solve?
Currently, pytest is difficult to use when testing bugs that cause your program to hang. By default, interrupting will mark the test as successful and no traceback is shown (related: #7640). So if it hangs you'll need to re-run your tests with the --full-trace flag (which can be annoying if the tests take a while or the problem is not consistently reproducible).
But when you use --full-trace it includes a bunch of frames from internal pytest and related libraries. i.e.:
anaconda3/envs/s/lib/python3.7/site-packages/pluggy/hooks.py
anaconda3/envs/s/lib/python3.7/site-packages/pluggy/manager.py
anaconda3/envs/s/lib/python3.7/site-packages/_pytest/python.py
anaconda3/envs/s/lib/python3.7/site-packages/_pytest/runner.py
... etc.
and makes the output SUUUUUPER LONG (like obscenely).
But 90% of the time, I don't care about all of those frames and it just makes the problem really hard and tedious to parse. I just want the frames related to my application.
I understand that those might be useful for debugging pytest, but I have personally used ctrl-c countless times to debug hanging programs and nearly every time I want to see the trace for my application and nothing else.
(I have also tried --full-trace --tb=native and --full-trace --tb=short with no change in behaviour).
Describe the solution you'd like
I would like a way to tell pytest to enable stack traces for keyboard interrupt, only including the frames that are relevant to my application.
The clearest solution that I can think of would be to add a --ctrlc-trace CLI flag
Basically, I'm suggesting decoupling --full-trace with showing the ctrl-c output because --full-trace has the additional connotation of "show me every possible frame including everything in pytest" which is something I have never wanted.
Alternatives
- Setting a global variable in your
test_something.pyfile (__keyboardinterrupt_trace__ = True) - Setting an attribute in pytest (e.g.
pytest.__keyboardinterrupt_trace__ = True) in yourtest_something.py - Have a list of paths to filter from tracebacks (e.g.
pytest.ignore_stack_trace_matching.append('ignored1', 'ignored2')
Path to a solution
Doing a quick look thru the source, the logic already partially exists
pytest/src/_pytest/_code/code.py
Line 1246 in 483f239
| def filter_traceback(entry: TracebackEntry) -> bool: |
And maybe it just involves adding another option and checking it here
pytest/src/_pytest/terminal.py
Line 857 in 483f239
| if self.config.option.fulltrace: |
i.e.
if self.config.option.fulltrace or self.config.option.ctrlctrace:
...since it looks like the full unfiltered trace is being enforced here, so by adding the second option, the kb interrupt output can be shown without being forced to use style == 'long'
pytest/src/_pytest/config/__init__.py
Lines 1059 to 1062 in c82bda2
| if option and getattr(option, "fulltrace", False): | |
| style: _TracebackStyle = "long" | |
| else: | |
| style = "native" |
(I am not familiar with the pytest source and I didn't do a deep dive so I'm sure I'm missing a thing or two)
Additional context
pytest 6.2.5