Skip to content

Commit 86c7dcf

Browse files
committed
pdb: handle quitting in post_mortem
`help quit` in pdb says: > Quit from the debugger. The program being executed is aborted. But pytest would continue with the next tests, often making it necessary to kill the pytest process when using `--pdb` and trying to cancel the tests using `KeyboardInterrupt` / `Ctrl-C`.
1 parent 27d2683 commit 86c7dcf

File tree

2 files changed

+18
-5
lines changed

2 files changed

+18
-5
lines changed

src/_pytest/debugging.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
""" interactive debugging with PDB, the Python Debugger. """
22
from __future__ import absolute_import, division, print_function
3+
4+
import os
35
import pdb
46
import sys
5-
import os
67
from doctest import UnexpectedException
78

9+
from _pytest import outcomes
810
from _pytest.config import hookimpl
911

1012
try:
@@ -164,8 +166,9 @@ def _enter_pdb(node, excinfo, rep):
164166
rep.toterminal(tw)
165167
tw.sep(">", "entering PDB")
166168
tb = _postmortem_traceback(excinfo)
167-
post_mortem(tb)
168169
rep._pdbshown = True
170+
if post_mortem(tb):
171+
outcomes.exit("Quitting debugger")
169172
return rep
170173

171174

@@ -196,3 +199,4 @@ def get_stack(self, f, t):
196199
p = Pdb()
197200
p.reset()
198201
p.interaction(None, t)
202+
return p.quitting

testing/test_pdb.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ def custom_pdb_calls():
2525

2626
# install dummy debugger class and track which methods were called on it
2727
class _CustomPdb(object):
28+
quitting = False
29+
2830
def __init__(self, *args, **kwargs):
2931
called.append("init")
3032

@@ -142,6 +144,9 @@ def test_pdb_interaction(self, testdir):
142144
def test_1():
143145
i = 0
144146
assert i == 1
147+
148+
def test_not_called_due_to_quit():
149+
pass
145150
"""
146151
)
147152
child = testdir.spawn_pytest("--pdb %s" % p1)
@@ -150,8 +155,9 @@ def test_1():
150155
child.expect("Pdb")
151156
child.sendeof()
152157
rest = child.read().decode("utf8")
153-
assert "1 failed" in rest
158+
assert "= 1 failed in" in rest
154159
assert "def test_1" not in rest
160+
assert "Exit: Quitting debugger" in rest
155161
self.flush(child)
156162

157163
@staticmethod
@@ -321,7 +327,7 @@ def test_pdb_interaction_on_collection_issue181(self, testdir):
321327
child = testdir.spawn_pytest("--pdb %s" % p1)
322328
# child.expect(".*import pytest.*")
323329
child.expect("Pdb")
324-
child.sendeof()
330+
child.sendline("c")
325331
child.expect("1 error")
326332
self.flush(child)
327333

@@ -376,6 +382,7 @@ def test_1():
376382
rest = child.read().decode("utf8")
377383
assert "1 failed" in rest
378384
assert "reading from stdin while output" not in rest
385+
assert "BdbQuit" in rest
379386
self.flush(child)
380387

381388
def test_pdb_and_capsys(self, testdir):
@@ -518,7 +525,9 @@ def test_foo(a):
518525
def test_pdb_collection_failure_is_shown(self, testdir):
519526
p1 = testdir.makepyfile("xxx")
520527
result = testdir.runpytest_subprocess("--pdb", p1)
521-
result.stdout.fnmatch_lines(["*NameError*xxx*", "*1 error*"])
528+
result.stdout.fnmatch_lines(
529+
["E NameError: *xxx*", "*! *Exit: Quitting debugger !*"] # due to EOF
530+
)
522531

523532
def test_enter_pdb_hook_is_called(self, testdir):
524533
testdir.makeconftest(

0 commit comments

Comments
 (0)