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:
holger krekel 2010-10-06 14:48:24 +02:00
parent 60a9b60634
commit eccc2a868c
4 changed files with 97 additions and 3 deletions

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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()