--pdb treats KeyboardInterrupt as exception

This commit is contained in:
Brian Maissy 2018-05-02 00:58:35 +03:00
parent 5ba0663827
commit c258fe1459
5 changed files with 23 additions and 8 deletions

View File

@ -16,7 +16,7 @@ def pytest_addoption(parser):
group = parser.getgroup("general") group = parser.getgroup("general")
group._addoption( group._addoption(
'--pdb', dest="usepdb", action="store_true", '--pdb', dest="usepdb", action="store_true",
help="start the interactive Python debugger on errors.") help="start the interactive Python debugger on errors or KeyboardInterrupt.")
group._addoption( group._addoption(
'--pdbcls', dest="usepdb_cls", metavar="modulename:classname", '--pdbcls', dest="usepdb_cls", metavar="modulename:classname",
help="start a custom interactive Python debugger on errors. " help="start a custom interactive Python debugger on errors. "

View File

@ -176,7 +176,8 @@ def check_interactive_exception(call, report):
def call_runtest_hook(item, when, **kwds): def call_runtest_hook(item, when, **kwds):
hookname = "pytest_runtest_" + when hookname = "pytest_runtest_" + when
ihook = getattr(item.ihook, hookname) ihook = getattr(item.ihook, hookname)
return CallInfo(lambda: ihook(item=item, **kwds), when=when) return CallInfo(lambda: ihook(item=item, **kwds), when=when,
treat_keyboard_interrupt_as_exception=item.config.getvalue("usepdb"))
class CallInfo(object): class CallInfo(object):
@ -184,7 +185,7 @@ class CallInfo(object):
#: None or ExceptionInfo object. #: None or ExceptionInfo object.
excinfo = None excinfo = None
def __init__(self, func, when): def __init__(self, func, when, treat_keyboard_interrupt_as_exception=False):
#: context of invocation: one of "setup", "call", #: context of invocation: one of "setup", "call",
#: "teardown", "memocollect" #: "teardown", "memocollect"
self.when = when self.when = when
@ -192,6 +193,9 @@ class CallInfo(object):
try: try:
self.result = func() self.result = func()
except KeyboardInterrupt: except KeyboardInterrupt:
if treat_keyboard_interrupt_as_exception:
self.excinfo = ExceptionInfo()
else:
self.stop = time() self.stop = time()
raise raise
except: # noqa except: # noqa

View File

@ -0,0 +1,2 @@
The ``--pdb`` option now causes KeyboardInterrupt to enter the debugger, instead of stopping the test session.
On python 2.7, hitting CTRL+C again exits the debugger. On python 3.2 and higher, use CTRL+D.

View File

@ -152,9 +152,9 @@ allows one to drop into the PDB_ prompt via a command line option::
pytest --pdb pytest --pdb
This will invoke the Python debugger on every failure. Often you might This will invoke the Python debugger on every failure (or KeyboardInterrupt).
only want to do this for the first failing test to understand a certain Often you might only want to do this for the first failing test to understand
failure situation:: a certain failure situation::
pytest -x --pdb # drop to PDB on first failure, then end test session pytest -x --pdb # drop to PDB on first failure, then end test session
pytest --pdb --maxfail=3 # drop to PDB for first three failures pytest --pdb --maxfail=3 # drop to PDB for first three failures

View File

@ -2,6 +2,7 @@ from __future__ import absolute_import, division, print_function
import sys import sys
import platform import platform
import os import os
import signal
import _pytest._code import _pytest._code
from _pytest.debugging import SUPPORTS_BREAKPOINT_BUILTIN from _pytest.debugging import SUPPORTS_BREAKPOINT_BUILTIN
@ -114,6 +115,14 @@ class TestPDB(object):
assert rep.failed assert rep.failed
assert len(pdblist) == 0 assert len(pdblist) == 0
def test_pdb_on_KeyboardInterrupt(self, testdir, pdblist):
rep = runpdb_and_get_report(testdir, """
def test_func():
raise KeyboardInterrupt
""")
assert rep.failed
assert len(pdblist) == 1
def test_pdb_interaction(self, testdir): def test_pdb_interaction(self, testdir):
p1 = testdir.makepyfile(""" p1 = testdir.makepyfile("""
def test_1(): def test_1():