Merge pull request #3436 from brianmaissy/feature/enter_pdb_on_keyboard_interrupt

--pdb treats KeyboardInterrupt as exception
This commit is contained in:
Bruno Oliveira 2018-05-03 12:20:43 -03:00 committed by GitHub
commit b03b387861
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 22 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,8 +193,11 @@ class CallInfo(object):
try: try:
self.result = func() self.result = func()
except KeyboardInterrupt: except KeyboardInterrupt:
self.stop = time() if treat_keyboard_interrupt_as_exception:
raise self.excinfo = ExceptionInfo()
else:
self.stop = time()
raise
except: # noqa except: # noqa
self.excinfo = ExceptionInfo() self.excinfo = ExceptionInfo()
self.stop = time() self.stop = time()

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

@ -114,6 +114,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():