diff --git a/changelog/4968.bugfix.rst b/changelog/4968.bugfix.rst new file mode 100644 index 00000000000..9ff61652eb4 --- /dev/null +++ b/changelog/4968.bugfix.rst @@ -0,0 +1,3 @@ +The pdb ``quit`` command is handled properly when used after the ``debug`` command with `pdb++`_. + +.. _pdb++: https://pypi.org/project/pdbpp/ diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index bb90d00ca88..cb1c964c35b 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -176,8 +176,15 @@ def do_continue(self, arg): do_c = do_cont = do_continue def set_quit(self): + """Raise Exit outcome when quit command is used in pdb. + + This is a bit of a hack - it would be better if BdbQuit + could be handled, but this would require to wrap the + whole pytest run, and adjust the report etc. + """ super(_PdbWrapper, self).set_quit() - outcomes.exit("Quitting debugger") + if cls._recursive_debug == 0: + outcomes.exit("Quitting debugger") def setup(self, f, tb): """Suspend on setup(). diff --git a/testing/test_pdb.py b/testing/test_pdb.py index d5cf17ef9ba..531846e8e13 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -519,7 +519,10 @@ def test_1(): assert "1 failed" in rest self.flush(child) - def test_pdb_interaction_continue_recursive(self, testdir): + def test_pdb_with_injected_do_debug(self, testdir): + """Simulates pdbpp, which injects Pdb into do_debug, and uses + self.__class__ in do_continue. + """ p1 = testdir.makepyfile( mytest=""" import pdb @@ -527,8 +530,6 @@ def test_pdb_interaction_continue_recursive(self, testdir): count_continue = 0 - # Simulates pdbpp, which injects Pdb into do_debug, and uses - # self.__class__ in do_continue. class CustomPdb(pdb.Pdb, object): def do_debug(self, arg): import sys @@ -578,6 +579,14 @@ def test_1(): assert b"PDB continue" not in child.before # No extra newline. assert child.before.endswith(b"c\r\nprint_from_foo\r\n") + + # set_debug should not raise outcomes.Exit, if used recrursively. + child.sendline("debug 42") + child.sendline("q") + child.expect("LEAVING RECURSIVE DEBUGGER") + assert b"ENTERING RECURSIVE DEBUGGER" in child.before + assert b"Quitting debugger" not in child.before + child.sendline("c") child.expect(r"PDB continue \(IO-capturing resumed\)") rest = child.read().decode("utf8")