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],
|
outerr = (item.outerr[0] + outerr[0],
|
||||||
item.outerr[1] + outerr[1])
|
item.outerr[1] + outerr[1])
|
||||||
return outerr
|
return outerr
|
||||||
|
if hasattr(item, 'outerr'):
|
||||||
|
return item.outerr
|
||||||
return "", ""
|
return "", ""
|
||||||
|
|
||||||
def activate_funcargs(self, pyfuncitem):
|
def activate_funcargs(self, pyfuncitem):
|
||||||
|
|
|
@ -10,10 +10,38 @@ def pytest_addoption(parser):
|
||||||
action="store_true", dest="usepdb", default=False,
|
action="store_true", dest="usepdb", default=False,
|
||||||
help="start the interactive Python debugger on errors.")
|
help="start the interactive Python debugger on errors.")
|
||||||
|
|
||||||
|
def pytest_namespace():
|
||||||
|
return {'set_trace': pytestPDB().set_trace}
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
if config.getvalue("usepdb"):
|
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:
|
class PdbInvoke:
|
||||||
def pytest_sessionfinish(self, session):
|
def pytest_sessionfinish(self, session):
|
||||||
# don't display failures again at the end
|
# don't display failures again at the end
|
||||||
|
|
|
@ -351,13 +351,17 @@ class TmpTestdir:
|
||||||
return self.runpybin("py.test", *args)
|
return self.runpybin("py.test", *args)
|
||||||
|
|
||||||
def spawn_pytest(self, string, expect_timeout=10.0):
|
def spawn_pytest(self, string, expect_timeout=10.0):
|
||||||
pexpect = py.test.importorskip("pexpect", "2.4")
|
|
||||||
if self.request.config.getvalue("notoolsonpath"):
|
if self.request.config.getvalue("notoolsonpath"):
|
||||||
py.test.skip("--no-tools-on-path prevents running pexpect-spawn tests")
|
py.test.skip("--no-tools-on-path prevents running pexpect-spawn tests")
|
||||||
basetemp = self.tmpdir.mkdir("pexpect")
|
basetemp = self.tmpdir.mkdir("pexpect")
|
||||||
invoke = self._getpybinargs("py.test")[0]
|
invoke = self._getpybinargs("py.test")[0]
|
||||||
cmd = "%s --basetemp=%s %s" % (invoke, basetemp, string)
|
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
|
child.timeout = expect_timeout
|
||||||
return child
|
return child
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import py
|
import py
|
||||||
|
import sys
|
||||||
|
|
||||||
class TestPDB:
|
class TestPDB:
|
||||||
def pytest_funcarg__pdblist(self, request):
|
def pytest_funcarg__pdblist(self, request):
|
||||||
|
@ -83,3 +84,62 @@ class TestPDB:
|
||||||
child.expect("1 failed")
|
child.expect("1 failed")
|
||||||
if child.isalive():
|
if child.isalive():
|
||||||
child.wait()
|
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