2010-10-06 20:48:24 +08:00
|
|
|
import sys
|
2016-10-22 00:36:42 +08:00
|
|
|
import platform
|
2009-09-06 22:59:39 +08:00
|
|
|
|
2015-11-27 22:43:01 +08:00
|
|
|
import _pytest._code
|
2016-07-12 09:03:53 +08:00
|
|
|
import pytest
|
2015-11-27 22:43:01 +08:00
|
|
|
|
|
|
|
|
2015-04-28 17:54:53 +08:00
|
|
|
def runpdb_and_get_report(testdir, source):
|
|
|
|
p = testdir.makepyfile(source)
|
|
|
|
result = testdir.runpytest_inprocess("--pdb", p)
|
|
|
|
reports = result.reprec.getreports("pytest_runtest_logreport")
|
|
|
|
assert len(reports) == 3, reports # setup/call/teardown
|
|
|
|
return reports[1]
|
|
|
|
|
2013-09-06 17:56:04 +08:00
|
|
|
|
2010-07-27 03:15:15 +08:00
|
|
|
class TestPDB:
|
2016-07-12 09:03:53 +08:00
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
def pdblist(self, request):
|
2016-06-21 18:09:55 +08:00
|
|
|
monkeypatch = request.getfixturevalue("monkeypatch")
|
2009-09-06 22:59:39 +08:00
|
|
|
pdblist = []
|
2016-11-21 04:59:15 +08:00
|
|
|
|
2009-09-06 22:59:39 +08:00
|
|
|
def mypdb(*args):
|
|
|
|
pdblist.append(args)
|
2016-11-21 04:59:15 +08:00
|
|
|
|
2016-06-25 18:37:31 +08:00
|
|
|
plugin = request.config.pluginmanager.getplugin('debugging')
|
2009-09-06 22:59:39 +08:00
|
|
|
monkeypatch.setattr(plugin, 'post_mortem', mypdb)
|
2010-07-27 03:15:15 +08:00
|
|
|
return pdblist
|
|
|
|
|
2009-09-06 22:59:39 +08:00
|
|
|
def test_pdb_on_fail(self, testdir, pdblist):
|
2015-04-28 17:54:53 +08:00
|
|
|
rep = runpdb_and_get_report(testdir, """
|
2010-07-27 03:15:15 +08:00
|
|
|
def test_func():
|
2009-09-06 22:59:39 +08:00
|
|
|
assert 0
|
|
|
|
""")
|
|
|
|
assert rep.failed
|
|
|
|
assert len(pdblist) == 1
|
2015-11-27 22:43:01 +08:00
|
|
|
tb = _pytest._code.Traceback(pdblist[0][0])
|
2009-09-06 22:59:39 +08:00
|
|
|
assert tb[-1].name == "test_func"
|
|
|
|
|
2010-06-16 18:35:08 +08:00
|
|
|
def test_pdb_on_xfail(self, testdir, pdblist):
|
2015-04-28 17:54:53 +08:00
|
|
|
rep = runpdb_and_get_report(testdir, """
|
2010-11-18 05:12:16 +08:00
|
|
|
import pytest
|
|
|
|
@pytest.mark.xfail
|
2010-07-27 03:15:15 +08:00
|
|
|
def test_func():
|
2010-06-16 18:35:08 +08:00
|
|
|
assert 0
|
|
|
|
""")
|
|
|
|
assert "xfail" in rep.keywords
|
2010-07-27 03:15:15 +08:00
|
|
|
assert not pdblist
|
2010-06-16 18:35:08 +08:00
|
|
|
|
2009-09-06 22:59:39 +08:00
|
|
|
def test_pdb_on_skip(self, testdir, pdblist):
|
2015-04-28 17:54:53 +08:00
|
|
|
rep = runpdb_and_get_report(testdir, """
|
2010-11-18 05:12:16 +08:00
|
|
|
import pytest
|
2009-09-06 22:59:39 +08:00
|
|
|
def test_func():
|
2010-11-18 05:12:16 +08:00
|
|
|
pytest.skip("hello")
|
2009-09-06 22:59:39 +08:00
|
|
|
""")
|
2010-07-27 03:15:15 +08:00
|
|
|
assert rep.skipped
|
2009-09-06 22:59:39 +08:00
|
|
|
assert len(pdblist) == 0
|
|
|
|
|
2010-10-06 20:28:06 +08:00
|
|
|
def test_pdb_on_BdbQuit(self, testdir, pdblist):
|
2015-04-28 17:54:53 +08:00
|
|
|
rep = runpdb_and_get_report(testdir, """
|
2010-11-18 05:12:16 +08:00
|
|
|
import bdb
|
2010-10-06 20:28:06 +08:00
|
|
|
def test_func():
|
|
|
|
raise bdb.BdbQuit
|
|
|
|
""")
|
|
|
|
assert rep.failed
|
|
|
|
assert len(pdblist) == 0
|
|
|
|
|
2009-09-06 22:59:39 +08:00
|
|
|
def test_pdb_interaction(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
|
|
|
def test_1():
|
|
|
|
i = 0
|
|
|
|
assert i == 1
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest("--pdb %s" % p1)
|
2009-12-25 02:43:14 +08:00
|
|
|
child.expect(".*def test_1")
|
|
|
|
child.expect(".*i = 0")
|
2009-09-06 22:59:39 +08:00
|
|
|
child.expect("(Pdb)")
|
|
|
|
child.sendeof()
|
2013-11-19 17:10:27 +08:00
|
|
|
rest = child.read().decode("utf8")
|
2010-06-17 18:53:29 +08:00
|
|
|
assert "1 failed" in rest
|
2010-07-27 03:15:15 +08:00
|
|
|
assert "def test_1" not in rest
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def flush(child):
|
2016-10-22 00:36:42 +08:00
|
|
|
if platform.system() == 'Darwin':
|
|
|
|
return
|
2010-07-27 03:15:15 +08:00
|
|
|
if child.isalive():
|
2009-09-06 22:59:39 +08:00
|
|
|
child.wait()
|
2010-02-08 21:17:01 +08:00
|
|
|
|
2016-09-01 02:22:54 +08:00
|
|
|
def test_pdb_unittest_postmortem(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
|
|
|
import unittest
|
|
|
|
class Blub(unittest.TestCase):
|
|
|
|
def tearDown(self):
|
|
|
|
self.filename = None
|
|
|
|
def test_false(self):
|
2016-09-01 04:33:47 +08:00
|
|
|
self.filename = 'debug' + '.me'
|
2016-09-01 02:22:54 +08:00
|
|
|
assert 0
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest("--pdb %s" % p1)
|
|
|
|
child.expect('(Pdb)')
|
|
|
|
child.sendline('p self.filename')
|
|
|
|
child.sendeof()
|
|
|
|
rest = child.read().decode("utf8")
|
2016-09-01 04:33:47 +08:00
|
|
|
assert 'debug.me' in rest
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2016-09-01 02:22:54 +08:00
|
|
|
|
2017-01-31 04:20:12 +08:00
|
|
|
def test_pdb_unittest_skip(self, testdir):
|
2017-02-02 12:01:51 +08:00
|
|
|
"""Test for issue #2137"""
|
2017-01-31 04:20:12 +08:00
|
|
|
p1 = testdir.makepyfile("""
|
|
|
|
import unittest
|
|
|
|
@unittest.skipIf(True, 'Skipping also with pdb active')
|
|
|
|
class MyTestCase(unittest.TestCase):
|
|
|
|
def test_one(self):
|
|
|
|
assert 0
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest("-rs --pdb %s" % p1)
|
|
|
|
child.expect('Skipping also with pdb active')
|
|
|
|
child.expect('1 skipped in')
|
|
|
|
child.sendeof()
|
|
|
|
self.flush(child)
|
|
|
|
|
2016-01-08 20:41:01 +08:00
|
|
|
def test_pdb_interaction_capture(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
|
|
|
def test_1():
|
|
|
|
print("getrekt")
|
|
|
|
assert False
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest("--pdb %s" % p1)
|
|
|
|
child.expect("getrekt")
|
|
|
|
child.expect("(Pdb)")
|
|
|
|
child.sendeof()
|
|
|
|
rest = child.read().decode("utf8")
|
|
|
|
assert "1 failed" in rest
|
|
|
|
assert "getrekt" not in rest
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2016-01-08 20:41:01 +08:00
|
|
|
|
2010-02-08 21:17:01 +08:00
|
|
|
def test_pdb_interaction_exception(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
2010-11-18 05:12:16 +08:00
|
|
|
import pytest
|
2010-02-08 21:17:01 +08:00
|
|
|
def globalfunc():
|
|
|
|
pass
|
|
|
|
def test_1():
|
2010-11-18 05:12:16 +08:00
|
|
|
pytest.raises(ValueError, globalfunc)
|
2010-02-08 21:17:01 +08:00
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest("--pdb %s" % p1)
|
|
|
|
child.expect(".*def test_1")
|
2010-11-18 05:12:16 +08:00
|
|
|
child.expect(".*pytest.raises.*globalfunc")
|
2010-02-08 21:17:01 +08:00
|
|
|
child.expect("(Pdb)")
|
|
|
|
child.sendline("globalfunc")
|
|
|
|
child.expect(".*function")
|
|
|
|
child.sendeof()
|
|
|
|
child.expect("1 failed")
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2010-10-06 20:48:24 +08:00
|
|
|
|
2013-09-06 17:56:04 +08:00
|
|
|
def test_pdb_interaction_on_collection_issue181(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
|
|
|
import pytest
|
|
|
|
xxx
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest("--pdb %s" % p1)
|
|
|
|
#child.expect(".*import pytest.*")
|
|
|
|
child.expect("(Pdb)")
|
|
|
|
child.sendeof()
|
|
|
|
child.expect("1 error")
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2013-09-06 17:56:04 +08:00
|
|
|
|
|
|
|
def test_pdb_interaction_on_internal_error(self, testdir):
|
|
|
|
testdir.makeconftest("""
|
|
|
|
def pytest_runtest_protocol():
|
|
|
|
0/0
|
|
|
|
""")
|
|
|
|
p1 = testdir.makepyfile("def test_func(): pass")
|
|
|
|
child = testdir.spawn_pytest("--pdb %s" % p1)
|
|
|
|
#child.expect(".*import pytest.*")
|
|
|
|
child.expect("(Pdb)")
|
|
|
|
child.sendeof()
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2013-09-06 17:56:04 +08:00
|
|
|
|
2010-10-06 20:48:24 +08:00
|
|
|
def test_pdb_interaction_capturing_simple(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
2010-11-18 05:12:16 +08:00
|
|
|
import pytest
|
2010-10-06 20:48:24 +08:00
|
|
|
def test_1():
|
|
|
|
i = 0
|
|
|
|
print ("hello17")
|
2010-11-18 05:12:16 +08:00
|
|
|
pytest.set_trace()
|
2010-10-06 20:48:24 +08:00
|
|
|
x = 3
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest(str(p1))
|
|
|
|
child.expect("test_1")
|
|
|
|
child.expect("x = 3")
|
|
|
|
child.expect("(Pdb)")
|
|
|
|
child.sendeof()
|
2013-11-19 17:10:27 +08:00
|
|
|
rest = child.read().decode("utf-8")
|
2010-10-06 20:48:24 +08:00
|
|
|
assert "1 failed" in rest
|
|
|
|
assert "def test_1" in rest
|
|
|
|
assert "hello17" in rest # out is captured
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2010-10-06 20:48:24 +08:00
|
|
|
|
2013-09-06 21:29:00 +08:00
|
|
|
def test_pdb_set_trace_interception(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
|
|
|
import pdb
|
|
|
|
def test_1():
|
|
|
|
pdb.set_trace()
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest(str(p1))
|
|
|
|
child.expect("test_1")
|
|
|
|
child.expect("(Pdb)")
|
|
|
|
child.sendeof()
|
2013-11-19 17:10:27 +08:00
|
|
|
rest = child.read().decode("utf8")
|
2013-09-06 21:29:00 +08:00
|
|
|
assert "1 failed" in rest
|
|
|
|
assert "reading from stdin while output" not in rest
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2013-09-06 21:29:00 +08:00
|
|
|
|
2012-11-22 03:43:31 +08:00
|
|
|
def test_pdb_and_capsys(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
|
|
|
import pytest
|
|
|
|
def test_1(capsys):
|
|
|
|
print ("hello1")
|
|
|
|
pytest.set_trace()
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest(str(p1))
|
|
|
|
child.expect("test_1")
|
|
|
|
child.send("capsys.readouterr()\n")
|
|
|
|
child.expect("hello1")
|
|
|
|
child.sendeof()
|
2013-10-12 21:39:22 +08:00
|
|
|
child.read()
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2012-11-22 03:43:31 +08:00
|
|
|
|
2014-04-01 20:32:12 +08:00
|
|
|
def test_set_trace_capturing_afterwards(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
|
|
|
import pdb
|
|
|
|
def test_1():
|
|
|
|
pdb.set_trace()
|
|
|
|
def test_2():
|
|
|
|
print ("hello")
|
|
|
|
assert 0
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest(str(p1))
|
|
|
|
child.expect("test_1")
|
|
|
|
child.send("c\n")
|
|
|
|
child.expect("test_2")
|
|
|
|
child.expect("Captured")
|
|
|
|
child.expect("hello")
|
|
|
|
child.sendeof()
|
|
|
|
child.read()
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2014-04-01 20:32:12 +08:00
|
|
|
|
2011-11-15 21:28:22 +08:00
|
|
|
def test_pdb_interaction_doctest(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
|
|
|
import pytest
|
|
|
|
def function_1():
|
|
|
|
'''
|
|
|
|
>>> i = 0
|
|
|
|
>>> assert i == 1
|
|
|
|
'''
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest("--doctest-modules --pdb %s" % p1)
|
|
|
|
child.expect("(Pdb)")
|
|
|
|
child.sendline('i')
|
|
|
|
child.expect("0")
|
|
|
|
child.expect("(Pdb)")
|
|
|
|
child.sendeof()
|
2013-11-19 17:10:27 +08:00
|
|
|
rest = child.read().decode("utf8")
|
2011-11-15 21:28:22 +08:00
|
|
|
assert "1 failed" in rest
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2011-11-15 21:28:22 +08:00
|
|
|
|
2010-10-06 20:48:24 +08:00
|
|
|
def test_pdb_interaction_capturing_twice(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
2010-11-18 05:12:16 +08:00
|
|
|
import pytest
|
2010-10-06 20:48:24 +08:00
|
|
|
def test_1():
|
|
|
|
i = 0
|
|
|
|
print ("hello17")
|
2010-11-18 05:12:16 +08:00
|
|
|
pytest.set_trace()
|
2010-10-06 20:48:24 +08:00
|
|
|
x = 3
|
|
|
|
print ("hello18")
|
2010-11-18 05:12:16 +08:00
|
|
|
pytest.set_trace()
|
2010-10-06 20:48:24 +08:00
|
|
|
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()
|
2013-11-19 17:10:27 +08:00
|
|
|
rest = child.read().decode("utf8")
|
2010-10-06 20:48:24 +08:00
|
|
|
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
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2010-10-06 20:48:24 +08:00
|
|
|
|
|
|
|
def test_pdb_used_outside_test(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
2010-11-18 05:12:16 +08:00
|
|
|
import pytest
|
|
|
|
pytest.set_trace()
|
2010-10-06 20:48:24 +08:00
|
|
|
x = 5
|
|
|
|
""")
|
|
|
|
child = testdir.spawn("%s %s" %(sys.executable, p1))
|
|
|
|
child.expect("x = 5")
|
|
|
|
child.sendeof()
|
2016-10-22 00:11:35 +08:00
|
|
|
self.flush(child)
|
2010-11-23 23:10:47 +08:00
|
|
|
|
2011-08-01 16:53:37 +08:00
|
|
|
def test_pdb_used_in_generate_tests(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""
|
|
|
|
import pytest
|
|
|
|
def pytest_generate_tests(metafunc):
|
|
|
|
pytest.set_trace()
|
|
|
|
x = 5
|
|
|
|
def test_foo(a):
|
|
|
|
pass
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest(str(p1))
|
|
|
|
child.expect("x = 5")
|
|
|
|
child.sendeof()
|
2016-10-22 00:11:35 +08:00
|
|
|
self.flush(child)
|
2013-11-19 17:10:27 +08:00
|
|
|
|
2010-11-23 23:10:47 +08:00
|
|
|
def test_pdb_collection_failure_is_shown(self, testdir):
|
|
|
|
p1 = testdir.makepyfile("""xxx """)
|
2015-04-28 17:54:46 +08:00
|
|
|
result = testdir.runpytest_subprocess("--pdb", p1)
|
2010-11-23 23:10:47 +08:00
|
|
|
result.stdout.fnmatch_lines([
|
|
|
|
"*NameError*xxx*",
|
|
|
|
"*1 error*",
|
|
|
|
])
|
2014-09-18 20:58:42 +08:00
|
|
|
|
|
|
|
def test_enter_pdb_hook_is_called(self, testdir):
|
|
|
|
testdir.makeconftest("""
|
2015-11-23 23:05:56 +08:00
|
|
|
def pytest_enter_pdb(config):
|
|
|
|
assert config.testing_verification == 'configured'
|
2014-09-18 20:58:42 +08:00
|
|
|
print 'enter_pdb_hook'
|
2015-11-23 23:05:56 +08:00
|
|
|
|
|
|
|
def pytest_configure(config):
|
|
|
|
config.testing_verification = 'configured'
|
2014-09-18 20:58:42 +08:00
|
|
|
""")
|
|
|
|
p1 = testdir.makepyfile("""
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
def test_foo():
|
|
|
|
pytest.set_trace()
|
|
|
|
""")
|
|
|
|
child = testdir.spawn_pytest(str(p1))
|
|
|
|
child.expect("enter_pdb_hook")
|
|
|
|
child.send('c\n')
|
|
|
|
child.sendeof()
|
2016-10-22 00:10:35 +08:00
|
|
|
self.flush(child)
|
2016-07-12 08:43:06 +08:00
|
|
|
|
|
|
|
def test_pdb_custom_cls(self, testdir):
|
|
|
|
called = []
|
|
|
|
|
|
|
|
# install dummy debugger class and track which methods were called on it
|
|
|
|
class _CustomPdb:
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
called.append("init")
|
|
|
|
|
|
|
|
def reset(self):
|
|
|
|
called.append("reset")
|
|
|
|
|
|
|
|
def interaction(self, *args):
|
|
|
|
called.append("interaction")
|
|
|
|
|
|
|
|
_pytest._CustomPdb = _CustomPdb
|
|
|
|
|
|
|
|
p1 = testdir.makepyfile("""xxx """)
|
|
|
|
result = testdir.runpytest_inprocess(
|
|
|
|
"--pdbcls=_pytest:_CustomPdb", p1)
|
|
|
|
result.stdout.fnmatch_lines([
|
|
|
|
"*NameError*xxx*",
|
|
|
|
"*1 error*",
|
|
|
|
])
|
|
|
|
assert called == ["init", "reset", "interaction"]
|