From 86c7dcff689ecb72a27f6d9dd48abf56bb9d969d Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 13 Oct 2018 16:49:30 +0200 Subject: [PATCH] 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`. --- src/_pytest/debugging.py | 8 ++++++-- testing/test_pdb.py | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index f51dff373..325cd60dd 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -1,10 +1,12 @@ """ interactive debugging with PDB, the Python Debugger. """ from __future__ import absolute_import, division, print_function + +import os import pdb import sys -import os from doctest import UnexpectedException +from _pytest import outcomes from _pytest.config import hookimpl try: @@ -164,8 +166,9 @@ def _enter_pdb(node, excinfo, rep): rep.toterminal(tw) tw.sep(">", "entering PDB") tb = _postmortem_traceback(excinfo) - post_mortem(tb) rep._pdbshown = True + if post_mortem(tb): + outcomes.exit("Quitting debugger") return rep @@ -196,3 +199,4 @@ def post_mortem(t): p = Pdb() p.reset() p.interaction(None, t) + return p.quitting diff --git a/testing/test_pdb.py b/testing/test_pdb.py index 4739f0e2d..4a5e740f7 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -25,6 +25,8 @@ def custom_pdb_calls(): # install dummy debugger class and track which methods were called on it class _CustomPdb(object): + quitting = False + def __init__(self, *args, **kwargs): called.append("init") @@ -142,6 +144,9 @@ class TestPDB(object): def test_1(): i = 0 assert i == 1 + + def test_not_called_due_to_quit(): + pass """ ) child = testdir.spawn_pytest("--pdb %s" % p1) @@ -150,8 +155,9 @@ class TestPDB(object): child.expect("Pdb") child.sendeof() rest = child.read().decode("utf8") - assert "1 failed" in rest + assert "= 1 failed in" in rest assert "def test_1" not in rest + assert "Exit: Quitting debugger" in rest self.flush(child) @staticmethod @@ -321,7 +327,7 @@ class TestPDB(object): child = testdir.spawn_pytest("--pdb %s" % p1) # child.expect(".*import pytest.*") child.expect("Pdb") - child.sendeof() + child.sendline("c") child.expect("1 error") self.flush(child) @@ -376,6 +382,7 @@ class TestPDB(object): rest = child.read().decode("utf8") assert "1 failed" in rest assert "reading from stdin while output" not in rest + assert "BdbQuit" in rest self.flush(child) def test_pdb_and_capsys(self, testdir): @@ -518,7 +525,9 @@ class TestPDB(object): def test_pdb_collection_failure_is_shown(self, testdir): p1 = testdir.makepyfile("xxx") result = testdir.runpytest_subprocess("--pdb", p1) - result.stdout.fnmatch_lines(["*NameError*xxx*", "*1 error*"]) + result.stdout.fnmatch_lines( + ["E NameError: *xxx*", "*! *Exit: Quitting debugger !*"] # due to EOF + ) def test_enter_pdb_hook_is_called(self, testdir): testdir.makeconftest(