fix issue126 : introduce py.test.set_trace() to allow dropping to
interactive debugging even when py.test is configured to capture output. If you like you can override pdb.set_trace by default like this: # content of conftest.py def pytest_configure(): import py, pdb pdb.set_trace = py.test.set_trace --HG-- branch : trunk
This commit is contained in:
parent
60a9b60634
commit
eccc2a868c
|
@ -182,6 +182,8 @@ class CaptureManager:
|
|||
outerr = (item.outerr[0] + outerr[0],
|
||||
item.outerr[1] + outerr[1])
|
||||
return outerr
|
||||
if hasattr(item, 'outerr'):
|
||||
return item.outerr
|
||||
return "", ""
|
||||
|
||||
def activate_funcargs(self, pyfuncitem):
|
||||
|
|
|
@ -10,10 +10,38 @@ def pytest_addoption(parser):
|
|||
action="store_true", dest="usepdb", default=False,
|
||||
help="start the interactive Python debugger on errors.")
|
||||
|
||||
def pytest_namespace():
|
||||
return {'set_trace': pytestPDB().set_trace}
|
||||
|
||||
def pytest_configure(config):
|
||||
if config.getvalue("usepdb"):
|
||||
config.pluginmanager.register(PdbInvoke(), 'pdb')
|
||||
config.pluginmanager.register(PdbInvoke(), 'pdbinvoke')
|
||||
|
||||
class pytestPDB:
|
||||
""" Pseudo PDB that defers to the real pdb. """
|
||||
item = None
|
||||
|
||||
def set_trace(self):
|
||||
""" invoke PDB set_trace debugging, dropping any IO capturing. """
|
||||
frame = sys._getframe().f_back
|
||||
item = getattr(self, 'item', None)
|
||||
if item is not None:
|
||||
capman = item.config.pluginmanager.getplugin("capturemanager")
|
||||
out, err = capman.suspendcapture()
|
||||
if hasattr(item, 'outerr'):
|
||||
item.outerr = (item.outerr[0] + out, item.outerr[1] + err)
|
||||
tw = py.io.TerminalWriter()
|
||||
tw.line()
|
||||
tw.sep(">", "PDB set_trace (IO-capturing turned off)")
|
||||
py.std.pdb.Pdb().set_trace(frame)
|
||||
|
||||
def pdbitem(item):
|
||||
pytestPDB.item = item
|
||||
pytest_runtest_setup = pytest_runtest_call = pytest_runtest_teardown = pdbitem
|
||||
|
||||
def pytest_runtest_makereport():
|
||||
pytestPDB.item = None
|
||||
|
||||
class PdbInvoke:
|
||||
def pytest_sessionfinish(self, session):
|
||||
# don't display failures again at the end
|
||||
|
|
|
@ -351,13 +351,17 @@ class TmpTestdir:
|
|||
return self.runpybin("py.test", *args)
|
||||
|
||||
def spawn_pytest(self, string, expect_timeout=10.0):
|
||||
pexpect = py.test.importorskip("pexpect", "2.4")
|
||||
if self.request.config.getvalue("notoolsonpath"):
|
||||
py.test.skip("--no-tools-on-path prevents running pexpect-spawn tests")
|
||||
basetemp = self.tmpdir.mkdir("pexpect")
|
||||
invoke = self._getpybinargs("py.test")[0]
|
||||
cmd = "%s --basetemp=%s %s" % (invoke, basetemp, string)
|
||||
child = pexpect.spawn(cmd, logfile=basetemp.join("spawn.out").open("w"))
|
||||
return self.spawn(cmd, expect_timeout=expect_timeout)
|
||||
|
||||
def spawn(self, cmd, expect_timeout=10.0):
|
||||
pexpect = py.test.importorskip("pexpect", "2.4")
|
||||
logfile = self.tmpdir.join("spawn.out")
|
||||
child = pexpect.spawn(cmd, logfile=logfile.open("w"))
|
||||
child.timeout = expect_timeout
|
||||
return child
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import py
|
||||
import sys
|
||||
|
||||
class TestPDB:
|
||||
def pytest_funcarg__pdblist(self, request):
|
||||
|
@ -83,3 +84,62 @@ class TestPDB:
|
|||
child.expect("1 failed")
|
||||
if child.isalive():
|
||||
child.wait()
|
||||
|
||||
def test_pdb_interaction_capturing_simple(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
import py
|
||||
def test_1():
|
||||
i = 0
|
||||
print ("hello17")
|
||||
py.test.set_trace()
|
||||
x = 3
|
||||
""")
|
||||
child = testdir.spawn_pytest(str(p1))
|
||||
child.expect("test_1")
|
||||
child.expect("x = 3")
|
||||
child.expect("(Pdb)")
|
||||
child.sendeof()
|
||||
rest = child.read()
|
||||
assert "1 failed" in rest
|
||||
assert "def test_1" in rest
|
||||
assert "hello17" in rest # out is captured
|
||||
if child.isalive():
|
||||
child.wait()
|
||||
|
||||
def test_pdb_interaction_capturing_twice(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
import py
|
||||
def test_1():
|
||||
i = 0
|
||||
print ("hello17")
|
||||
py.test.set_trace()
|
||||
x = 3
|
||||
print ("hello18")
|
||||
py.test.set_trace()
|
||||
x = 4
|
||||
""")
|
||||
child = testdir.spawn_pytest(str(p1))
|
||||
child.expect("test_1")
|
||||
child.expect("x = 3")
|
||||
child.expect("(Pdb)")
|
||||
child.sendline('c')
|
||||
child.expect("x = 4")
|
||||
child.sendeof()
|
||||
rest = child.read()
|
||||
assert "1 failed" in rest
|
||||
assert "def test_1" in rest
|
||||
assert "hello17" in rest # out is captured
|
||||
assert "hello18" in rest # out is captured
|
||||
if child.isalive():
|
||||
child.wait()
|
||||
|
||||
def test_pdb_used_outside_test(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
import py
|
||||
py.test.set_trace()
|
||||
x = 5
|
||||
""")
|
||||
child = testdir.spawn("%s %s" %(sys.executable, p1))
|
||||
child.expect("x = 5")
|
||||
child.sendeof()
|
||||
child.wait()
|
||||
|
|
Loading…
Reference in New Issue