Improve quitting from pdb
Regarding tests: 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).
This commit is contained in:
parent
4947eb85c0
commit
e69b1255d7
|
@ -0,0 +1,3 @@
|
||||||
|
Improve quitting from pdb, especially with ``--trace``.
|
||||||
|
|
||||||
|
Using ``q[quit]`` after ``pdb.set_trace()`` will quit pytest also.
|
|
@ -118,6 +118,10 @@ class pytestPDB(object):
|
||||||
|
|
||||||
do_c = do_cont = do_continue
|
do_c = do_cont = do_continue
|
||||||
|
|
||||||
|
def set_quit(self):
|
||||||
|
super(_PdbWrapper, self).set_quit()
|
||||||
|
outcomes.exit("Quitting debugger")
|
||||||
|
|
||||||
def setup(self, f, tb):
|
def setup(self, f, tb):
|
||||||
"""Suspend on setup().
|
"""Suspend on setup().
|
||||||
|
|
||||||
|
@ -210,8 +214,7 @@ def _enter_pdb(node, excinfo, rep):
|
||||||
tw.sep(">", "entering PDB")
|
tw.sep(">", "entering PDB")
|
||||||
tb = _postmortem_traceback(excinfo)
|
tb = _postmortem_traceback(excinfo)
|
||||||
rep._pdbshown = True
|
rep._pdbshown = True
|
||||||
if post_mortem(tb):
|
post_mortem(tb)
|
||||||
outcomes.exit("Quitting debugger")
|
|
||||||
return rep
|
return rep
|
||||||
|
|
||||||
|
|
||||||
|
@ -242,4 +245,5 @@ def post_mortem(t):
|
||||||
p = Pdb()
|
p = Pdb()
|
||||||
p.reset()
|
p.reset()
|
||||||
p.interaction(None, t)
|
p.interaction(None, t)
|
||||||
return p.quitting
|
if p.quitting:
|
||||||
|
outcomes.exit("Quitting debugger")
|
||||||
|
|
|
@ -49,13 +49,13 @@ class Failed(OutcomeException):
|
||||||
__module__ = "builtins"
|
__module__ = "builtins"
|
||||||
|
|
||||||
|
|
||||||
class Exit(SystemExit):
|
class Exit(Exception):
|
||||||
""" raised for immediate program exits (no tracebacks/summaries)"""
|
""" raised for immediate program exits (no tracebacks/summaries)"""
|
||||||
|
|
||||||
def __init__(self, msg="unknown reason", returncode=None):
|
def __init__(self, msg="unknown reason", returncode=None):
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
self.returncode = returncode
|
self.returncode = returncode
|
||||||
SystemExit.__init__(self, msg)
|
super(Exit, self).__init__(msg)
|
||||||
|
|
||||||
|
|
||||||
# exposed helper methods
|
# exposed helper methods
|
||||||
|
@ -63,7 +63,7 @@ class Exit(SystemExit):
|
||||||
|
|
||||||
def exit(msg, returncode=None):
|
def exit(msg, returncode=None):
|
||||||
"""
|
"""
|
||||||
Exit testing process as if SystemExit was triggered.
|
Exit testing process.
|
||||||
|
|
||||||
:param str msg: message to display upon exit.
|
:param str msg: message to display upon exit.
|
||||||
:param int returncode: return code to be used when exiting pytest.
|
:param int returncode: return code to be used when exiting pytest.
|
||||||
|
|
|
@ -147,29 +147,6 @@ class TestPDB(object):
|
||||||
assert rep.failed
|
assert rep.failed
|
||||||
assert len(pdblist) == 1
|
assert len(pdblist) == 1
|
||||||
|
|
||||||
def test_pdb_interaction(self, testdir):
|
|
||||||
p1 = testdir.makepyfile(
|
|
||||||
"""
|
|
||||||
def test_1():
|
|
||||||
i = 0
|
|
||||||
assert i == 1
|
|
||||||
|
|
||||||
def test_not_called_due_to_quit():
|
|
||||||
pass
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
|
||||||
child.expect(".*def test_1")
|
|
||||||
child.expect(".*i = 0")
|
|
||||||
child.expect("Pdb")
|
|
||||||
child.sendeof()
|
|
||||||
rest = child.read().decode("utf8")
|
|
||||||
assert "= 1 failed in" in rest
|
|
||||||
assert "def test_1" not in rest
|
|
||||||
assert "Exit: Quitting debugger" in rest
|
|
||||||
assert "PDB continue (IO-capturing resumed)" not in rest
|
|
||||||
self.flush(child)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def flush(child):
|
def flush(child):
|
||||||
if platform.system() == "Darwin":
|
if platform.system() == "Darwin":
|
||||||
|
@ -214,40 +191,32 @@ class TestPDB(object):
|
||||||
child.sendeof()
|
child.sendeof()
|
||||||
self.flush(child)
|
self.flush(child)
|
||||||
|
|
||||||
def test_pdb_print_captured_stdout(self, testdir):
|
def test_pdb_print_captured_stdout_and_stderr(self, testdir):
|
||||||
p1 = testdir.makepyfile(
|
|
||||||
"""
|
|
||||||
def test_1():
|
|
||||||
print("get\\x20rekt")
|
|
||||||
assert False
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
|
||||||
child.expect("captured stdout")
|
|
||||||
child.expect("get rekt")
|
|
||||||
child.expect("Pdb")
|
|
||||||
child.sendeof()
|
|
||||||
rest = child.read().decode("utf8")
|
|
||||||
assert "1 failed" in rest
|
|
||||||
assert "get rekt" not in rest
|
|
||||||
self.flush(child)
|
|
||||||
|
|
||||||
def test_pdb_print_captured_stderr(self, testdir):
|
|
||||||
p1 = testdir.makepyfile(
|
p1 = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
def test_1():
|
def test_1():
|
||||||
import sys
|
import sys
|
||||||
sys.stderr.write("get\\x20rekt")
|
sys.stderr.write("get\\x20rekt")
|
||||||
|
print("get\\x20rekt")
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
def test_not_called_due_to_quit():
|
||||||
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||||
|
child.expect("captured stdout")
|
||||||
|
child.expect("get rekt")
|
||||||
child.expect("captured stderr")
|
child.expect("captured stderr")
|
||||||
child.expect("get rekt")
|
child.expect("get rekt")
|
||||||
|
child.expect("traceback")
|
||||||
|
child.expect("def test_1")
|
||||||
child.expect("Pdb")
|
child.expect("Pdb")
|
||||||
child.sendeof()
|
child.sendeof()
|
||||||
rest = child.read().decode("utf8")
|
rest = child.read().decode("utf8")
|
||||||
assert "1 failed" in rest
|
assert "Exit: Quitting debugger" in rest
|
||||||
|
assert "= 1 failed in" in rest
|
||||||
|
assert "def test_1" not in rest
|
||||||
assert "get rekt" not in rest
|
assert "get rekt" not in rest
|
||||||
self.flush(child)
|
self.flush(child)
|
||||||
|
|
||||||
|
@ -375,15 +344,17 @@ class TestPDB(object):
|
||||||
i = 0
|
i = 0
|
||||||
print("hello17")
|
print("hello17")
|
||||||
pytest.set_trace()
|
pytest.set_trace()
|
||||||
x = 3
|
i == 1
|
||||||
|
assert 0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
child = testdir.spawn_pytest(str(p1))
|
child = testdir.spawn_pytest(str(p1))
|
||||||
child.expect("test_1")
|
child.expect(r"test_1\(\)")
|
||||||
child.expect("x = 3")
|
child.expect("i == 1")
|
||||||
child.expect("Pdb")
|
child.expect("Pdb")
|
||||||
child.sendeof()
|
child.sendline("c")
|
||||||
rest = child.read().decode("utf-8")
|
rest = child.read().decode("utf-8")
|
||||||
|
assert "AssertionError" in rest
|
||||||
assert "1 failed" in rest
|
assert "1 failed" in rest
|
||||||
assert "def test_1" in rest
|
assert "def test_1" in rest
|
||||||
assert "hello17" in rest # out is captured
|
assert "hello17" in rest # out is captured
|
||||||
|
@ -398,13 +369,14 @@ class TestPDB(object):
|
||||||
print("hello17")
|
print("hello17")
|
||||||
pytest.set_trace(header="== my_header ==")
|
pytest.set_trace(header="== my_header ==")
|
||||||
x = 3
|
x = 3
|
||||||
|
assert 0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
child = testdir.spawn_pytest(str(p1))
|
child = testdir.spawn_pytest(str(p1))
|
||||||
child.expect("== my_header ==")
|
child.expect("== my_header ==")
|
||||||
assert "PDB set_trace" not in child.before.decode()
|
assert "PDB set_trace" not in child.before.decode()
|
||||||
child.expect("Pdb")
|
child.expect("Pdb")
|
||||||
child.sendeof()
|
child.sendline("c")
|
||||||
rest = child.read().decode("utf-8")
|
rest = child.read().decode("utf-8")
|
||||||
assert "1 failed" in rest
|
assert "1 failed" in rest
|
||||||
assert "def test_1" in rest
|
assert "def test_1" in rest
|
||||||
|
@ -424,9 +396,9 @@ class TestPDB(object):
|
||||||
child.expect("Pdb")
|
child.expect("Pdb")
|
||||||
child.sendeof()
|
child.sendeof()
|
||||||
rest = child.read().decode("utf8")
|
rest = child.read().decode("utf8")
|
||||||
assert "1 failed" in rest
|
assert "no tests ran" in rest
|
||||||
assert "reading from stdin while output" not in rest
|
assert "reading from stdin while output" not in rest
|
||||||
assert "BdbQuit" in rest
|
assert "BdbQuit" not in rest
|
||||||
self.flush(child)
|
self.flush(child)
|
||||||
|
|
||||||
def test_pdb_and_capsys(self, testdir):
|
def test_pdb_and_capsys(self, testdir):
|
||||||
|
@ -518,6 +490,7 @@ class TestPDB(object):
|
||||||
print("hello18")
|
print("hello18")
|
||||||
pytest.set_trace()
|
pytest.set_trace()
|
||||||
x = 4
|
x = 4
|
||||||
|
assert 0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
child = testdir.spawn_pytest(str(p1))
|
child = testdir.spawn_pytest(str(p1))
|
||||||
|
@ -530,11 +503,11 @@ class TestPDB(object):
|
||||||
child.expect(r"PDB set_trace \(IO-capturing turned off\)")
|
child.expect(r"PDB set_trace \(IO-capturing turned off\)")
|
||||||
child.expect("x = 4")
|
child.expect("x = 4")
|
||||||
child.expect("Pdb")
|
child.expect("Pdb")
|
||||||
child.sendeof()
|
child.sendline("c")
|
||||||
child.expect("_ test_1 _")
|
child.expect("_ test_1 _")
|
||||||
child.expect("def test_1")
|
child.expect("def test_1")
|
||||||
child.expect("Captured stdout call")
|
|
||||||
rest = child.read().decode("utf8")
|
rest = child.read().decode("utf8")
|
||||||
|
assert "Captured stdout call" in rest
|
||||||
assert "hello17" in rest # out is captured
|
assert "hello17" in rest # out is captured
|
||||||
assert "hello18" in rest # out is captured
|
assert "hello18" in rest # out is captured
|
||||||
assert "1 failed" in rest
|
assert "1 failed" in rest
|
||||||
|
@ -795,7 +768,7 @@ class TestDebuggingBreakpoints(object):
|
||||||
child.expect("Pdb")
|
child.expect("Pdb")
|
||||||
child.sendeof()
|
child.sendeof()
|
||||||
rest = child.read().decode("utf8")
|
rest = child.read().decode("utf8")
|
||||||
assert "1 failed" in rest
|
assert "Quitting debugger" in rest
|
||||||
assert "reading from stdin while output" not in rest
|
assert "reading from stdin while output" not in rest
|
||||||
TestPDB.flush(child)
|
TestPDB.flush(child)
|
||||||
|
|
||||||
|
@ -808,12 +781,13 @@ class TestDebuggingBreakpoints(object):
|
||||||
import pdb
|
import pdb
|
||||||
def test_1():
|
def test_1():
|
||||||
pdb.set_trace()
|
pdb.set_trace()
|
||||||
|
assert 0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
child = testdir.spawn_pytest(str(p1))
|
child = testdir.spawn_pytest(str(p1))
|
||||||
child.expect("test_1")
|
child.expect("test_1")
|
||||||
child.expect("Pdb")
|
child.expect("Pdb")
|
||||||
child.sendeof()
|
child.sendline("c")
|
||||||
rest = child.read().decode("utf8")
|
rest = child.read().decode("utf8")
|
||||||
assert "1 failed" in rest
|
assert "1 failed" in rest
|
||||||
assert "reading from stdin while output" not in rest
|
assert "reading from stdin while output" not in rest
|
||||||
|
@ -826,15 +800,29 @@ class TestTraceOption:
|
||||||
"""
|
"""
|
||||||
def test_1():
|
def test_1():
|
||||||
assert True
|
assert True
|
||||||
|
|
||||||
|
def test_2():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_3():
|
||||||
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
child = testdir.spawn_pytest("--trace " + str(p1))
|
child = testdir.spawn_pytest("--trace " + str(p1))
|
||||||
child.expect("test_1")
|
child.expect("test_1")
|
||||||
child.expect("Pdb")
|
child.expect("Pdb")
|
||||||
child.sendeof()
|
child.sendline("c")
|
||||||
|
child.expect("test_2")
|
||||||
|
child.expect("Pdb")
|
||||||
|
child.sendline("c")
|
||||||
|
child.expect("test_3")
|
||||||
|
child.expect("Pdb")
|
||||||
|
child.sendline("q")
|
||||||
|
child.expect_exact("Exit: Quitting debugger")
|
||||||
rest = child.read().decode("utf8")
|
rest = child.read().decode("utf8")
|
||||||
assert "1 passed" in rest
|
assert "2 passed in" in rest
|
||||||
assert "reading from stdin while output" not in rest
|
assert "reading from stdin while output" not in rest
|
||||||
|
assert "Exit: Quitting debugger" in child.before.decode("utf8")
|
||||||
TestPDB.flush(child)
|
TestPDB.flush(child)
|
||||||
|
|
||||||
|
|
||||||
|
@ -863,3 +851,31 @@ def test_trace_after_runpytest(testdir):
|
||||||
rest = child.read().decode("utf8")
|
rest = child.read().decode("utf8")
|
||||||
TestPDB.flush(child)
|
TestPDB.flush(child)
|
||||||
assert child.exitstatus == 0, rest
|
assert child.exitstatus == 0, rest
|
||||||
|
|
||||||
|
|
||||||
|
def test_quit_with_swallowed_SystemExit(testdir):
|
||||||
|
"""Test that debugging's pytest_configure is re-entrant."""
|
||||||
|
p1 = testdir.makepyfile(
|
||||||
|
"""
|
||||||
|
def call_pdb_set_trace():
|
||||||
|
__import__('pdb').set_trace()
|
||||||
|
|
||||||
|
|
||||||
|
def test_1():
|
||||||
|
try:
|
||||||
|
call_pdb_set_trace()
|
||||||
|
except SystemExit:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_2():
|
||||||
|
pass
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
child = testdir.spawn_pytest(str(p1))
|
||||||
|
child.expect("Pdb")
|
||||||
|
child.sendline("q")
|
||||||
|
child.expect_exact("Exit: Quitting debugger")
|
||||||
|
rest = child.read().decode("utf8")
|
||||||
|
assert "no tests ran" in rest
|
||||||
|
TestPDB.flush(child)
|
||||||
|
|
Loading…
Reference in New Issue