Skip to content

Commit ad65ddb

Browse files
committed
Handle quitting from pdb with --trace
This raises ``outcomes.exit`` via ``set_quit``, and ``post_mortem`` directly already. It merges ``test_pdb_interaction``, ``test_pdb_print_captured_stdout``, and ``test_pdb_print_captured_stderr`` into ``test_pdb_print_captured_stdout_and_stderr`` (clarity and performance, especially since pexpect tests are slow).
1 parent 5dcb370 commit ad65ddb

File tree

3 files changed

+48
-56
lines changed

3 files changed

+48
-56
lines changed

changelog/4280.bugfix.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Handle quitting from pdb with ``--trace`` and parametrized tests by exiting pytest.
2+
3+
Using ``[q]uit`` when in pdb will now exit pytest, instead of continue to run
4+
the remaining tests.

src/_pytest/debugging.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ def do_continue(self, arg):
118118

119119
do_c = do_cont = do_continue
120120

121+
def set_quit(self):
122+
super(_PdbWrapper, self).set_quit()
123+
outcomes.exit("Quitting debugger")
124+
121125
def setup(self, f, tb):
122126
"""Suspend on setup().
123127
@@ -210,8 +214,7 @@ def _enter_pdb(node, excinfo, rep):
210214
tw.sep(">", "entering PDB")
211215
tb = _postmortem_traceback(excinfo)
212216
rep._pdbshown = True
213-
if post_mortem(tb):
214-
outcomes.exit("Quitting debugger")
217+
post_mortem(tb)
215218
return rep
216219

217220

@@ -242,4 +245,5 @@ def get_stack(self, f, t):
242245
p = Pdb()
243246
p.reset()
244247
p.interaction(None, t)
245-
return p.quitting
248+
if p.quitting:
249+
outcomes.exit("Quitting debugger")

testing/test_pdb.py

Lines changed: 37 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -147,29 +147,6 @@ def test_func():
147147
assert rep.failed
148148
assert len(pdblist) == 1
149149

150-
def test_pdb_interaction(self, testdir):
151-
p1 = testdir.makepyfile(
152-
"""
153-
def test_1():
154-
i = 0
155-
assert i == 1
156-
157-
def test_not_called_due_to_quit():
158-
pass
159-
"""
160-
)
161-
child = testdir.spawn_pytest("--pdb %s" % p1)
162-
child.expect(".*def test_1")
163-
child.expect(".*i = 0")
164-
child.expect("Pdb")
165-
child.sendeof()
166-
rest = child.read().decode("utf8")
167-
assert "= 1 failed in" in rest
168-
assert "def test_1" not in rest
169-
assert "Exit: Quitting debugger" in rest
170-
assert "PDB continue (IO-capturing resumed)" not in rest
171-
self.flush(child)
172-
173150
@staticmethod
174151
def flush(child):
175152
if platform.system() == "Darwin":
@@ -214,40 +191,32 @@ def test_one(self):
214191
child.sendeof()
215192
self.flush(child)
216193

217-
def test_pdb_print_captured_stdout(self, testdir):
194+
def test_pdb_print_captured_stdout_and_stderr(self, testdir):
218195
p1 = testdir.makepyfile(
219196
"""
220197
def test_1():
198+
import sys
199+
sys.stderr.write("get\\x20rekt")
221200
print("get\\x20rekt")
222201
assert False
202+
203+
def test_not_called_due_to_quit():
204+
pass
223205
"""
224206
)
225207
child = testdir.spawn_pytest("--pdb %s" % p1)
226208
child.expect("captured stdout")
227209
child.expect("get rekt")
228-
child.expect("Pdb")
229-
child.sendeof()
230-
rest = child.read().decode("utf8")
231-
assert "1 failed" in rest
232-
assert "get rekt" not in rest
233-
self.flush(child)
234-
235-
def test_pdb_print_captured_stderr(self, testdir):
236-
p1 = testdir.makepyfile(
237-
"""
238-
def test_1():
239-
import sys
240-
sys.stderr.write("get\\x20rekt")
241-
assert False
242-
"""
243-
)
244-
child = testdir.spawn_pytest("--pdb %s" % p1)
245210
child.expect("captured stderr")
246211
child.expect("get rekt")
212+
child.expect("traceback")
213+
child.expect("def test_1")
247214
child.expect("Pdb")
248215
child.sendeof()
249216
rest = child.read().decode("utf8")
250-
assert "1 failed" in rest
217+
assert "Exit: Quitting debugger" in rest
218+
assert "= 1 failed in" in rest
219+
assert "def test_1" not in rest
251220
assert "get rekt" not in rest
252221
self.flush(child)
253222

@@ -375,15 +344,17 @@ def test_1():
375344
i = 0
376345
print("hello17")
377346
pytest.set_trace()
378-
x = 3
347+
i == 1
348+
assert 0
379349
"""
380350
)
381351
child = testdir.spawn_pytest(str(p1))
382-
child.expect("test_1")
383-
child.expect("x = 3")
352+
child.expect(r"test_1\(\)")
353+
child.expect("i == 1")
384354
child.expect("Pdb")
385-
child.sendeof()
355+
child.sendline("c")
386356
rest = child.read().decode("utf-8")
357+
assert "AssertionError" in rest
387358
assert "1 failed" in rest
388359
assert "def test_1" in rest
389360
assert "hello17" in rest # out is captured
@@ -398,13 +369,14 @@ def test_1():
398369
print("hello17")
399370
pytest.set_trace(header="== my_header ==")
400371
x = 3
372+
assert 0
401373
"""
402374
)
403375
child = testdir.spawn_pytest(str(p1))
404376
child.expect("== my_header ==")
405377
assert "PDB set_trace" not in child.before.decode()
406378
child.expect("Pdb")
407-
child.sendeof()
379+
child.sendline("c")
408380
rest = child.read().decode("utf-8")
409381
assert "1 failed" in rest
410382
assert "def test_1" in rest
@@ -424,9 +396,9 @@ def test_1():
424396
child.expect("Pdb")
425397
child.sendeof()
426398
rest = child.read().decode("utf8")
427-
assert "1 failed" in rest
399+
assert "no tests ran" in rest
428400
assert "reading from stdin while output" not in rest
429-
assert "BdbQuit" in rest
401+
assert "BdbQuit" not in rest
430402
self.flush(child)
431403

432404
def test_pdb_and_capsys(self, testdir):
@@ -518,6 +490,7 @@ def test_1():
518490
print("hello18")
519491
pytest.set_trace()
520492
x = 4
493+
assert 0
521494
"""
522495
)
523496
child = testdir.spawn_pytest(str(p1))
@@ -530,11 +503,11 @@ def test_1():
530503
child.expect(r"PDB set_trace \(IO-capturing turned off\)")
531504
child.expect("x = 4")
532505
child.expect("Pdb")
533-
child.sendeof()
506+
child.sendline("c")
534507
child.expect("_ test_1 _")
535508
child.expect("def test_1")
536-
child.expect("Captured stdout call")
537509
rest = child.read().decode("utf8")
510+
assert "Captured stdout call" in rest
538511
assert "hello17" in rest # out is captured
539512
assert "hello18" in rest # out is captured
540513
assert "1 failed" in rest
@@ -826,15 +799,26 @@ def test_trace_sets_breakpoint(self, testdir):
826799
"""
827800
def test_1():
828801
assert True
802+
803+
def test_2():
804+
pass
805+
806+
def test_3():
807+
pass
829808
"""
830809
)
831810
child = testdir.spawn_pytest("--trace " + str(p1))
832811
child.expect("test_1")
833812
child.expect("Pdb")
834-
child.sendeof()
813+
child.sendline("c")
814+
child.expect("test_2")
815+
child.expect("Pdb")
816+
child.sendline("q")
817+
child.expect_exact("Exit: Quitting debugger")
835818
rest = child.read().decode("utf8")
836-
assert "1 passed" in rest
819+
assert "1 passed in" in rest
837820
assert "reading from stdin while output" not in rest
821+
assert "Exit: Quitting debugger" in child.before.decode("utf8")
838822
TestPDB.flush(child)
839823

840824

0 commit comments

Comments
 (0)