def test_enter_leave_pdb_hooks_are_called(self, post_mortem, pytester: Pytester) -> None: pytester.makeconftest(""" mypdb = None def pytest_configure(config): config.testing_verification = 'configured' def pytest_enter_pdb(config, pdb): assert config.testing_verification == 'configured' print('enter_pdb_hook') global mypdb mypdb = pdb mypdb.set_attribute = "bar" def pytest_leave_pdb(config, pdb): assert config.testing_verification == 'configured' print('leave_pdb_hook') global mypdb assert mypdb is pdb assert mypdb.set_attribute == "bar" """) p1 = pytester.makepyfile(""" import pytest def test_set_trace(): pytest.set_trace() assert 0 def test_post_mortem(): assert 0 """) if post_mortem: child = pytester.spawn_pytest( str(p1) + " --pdb -s -k test_post_mortem") else: child = pytester.spawn_pytest(str(p1) + " -k test_set_trace") child.expect("enter_pdb_hook") child.sendline("c") if post_mortem: child.expect(r"PDB continue") else: child.expect(r"PDB continue \(IO-capturing resumed\)") child.expect("Captured stdout call") rest = child.read().decode("utf8") assert "leave_pdb_hook" in rest assert "1 failed" in rest self.flush(child)
def test_pdb_print_captured_stdout_and_stderr(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" def test_1(): import sys sys.stderr.write("get\\x20rekt") print("get\\x20rekt") assert False def test_not_called_due_to_quit(): pass """) child = pytester.spawn_pytest("--pdb %s" % p1) child.expect("captured stdout") child.expect("get rekt") child.expect("captured stderr") child.expect("get rekt") child.expect("traceback") child.expect("def test_1") child.expect("Pdb") child.sendeof() rest = child.read().decode("utf8") 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 self.flush(child)
def test_pdb_interaction_capturing_twice(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pytest def test_1(): i = 0 print("hello17") pytest.set_trace() x = 3 print("hello18") pytest.set_trace() x = 4 assert 0 """) child = pytester.spawn_pytest(str(p1)) child.expect(r"PDB set_trace \(IO-capturing turned off\)") child.expect("test_1") child.expect("x = 3") child.expect("Pdb") child.sendline("c") child.expect(r"PDB continue \(IO-capturing resumed\)") child.expect(r"PDB set_trace \(IO-capturing turned off\)") child.expect("x = 4") child.expect("Pdb") child.sendline("c") child.expect("_ test_1 _") child.expect("def test_1") rest = child.read().decode("utf8") assert "Captured stdout call" in rest assert "hello17" in rest # out is captured assert "hello18" in rest # out is captured assert "1 failed" in rest self.flush(child)
def test_pdb_custom_cls_with_set_trace( self, pytester: Pytester, monkeypatch: MonkeyPatch, ) -> None: pytester.makepyfile(custom_pdb=""" class CustomPdb(object): def __init__(self, *args, **kwargs): skip = kwargs.pop("skip") assert skip == ["foo.*"] print("__init__") super(CustomPdb, self).__init__(*args, **kwargs) def set_trace(*args, **kwargs): print('custom set_trace>') """) p1 = pytester.makepyfile(""" import pytest def test_foo(): pytest.set_trace(skip=['foo.*']) """) monkeypatch.setenv("PYTHONPATH", str(pytester.path)) child = pytester.spawn_pytest("--pdbcls=custom_pdb:CustomPdb %s" % str(p1)) child.expect("__init__") child.expect("custom set_trace>") self.flush(child)
def test_trace_sets_breakpoint(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" def test_1(): assert True def test_2(): pass def test_3(): pass """) child = pytester.spawn_pytest("--trace " + str(p1)) child.expect("test_1") child.expect("Pdb") 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") assert "= 2 passed in" in rest assert "reading from stdin while output" not in rest # Only printed once - not on stderr. assert "Exit: Quitting debugger" not in child.before.decode("utf8") TestPDB.flush(child)
def test_trial_pdb(self, pytester: Pytester) -> None: p = pytester.makepyfile(""" from twisted.trial import unittest import pytest class TC(unittest.TestCase): def test_hello(self): assert 0, "hellopdb" """) child = pytester.spawn_pytest(str(p)) child.expect("hellopdb") child.sendeof()
def test_pdb_interaction_on_collection_issue181( self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pytest xxx """) child = pytester.spawn_pytest("--pdb %s" % p1) # child.expect(".*import pytest.*") child.expect("Pdb") child.sendline("c") child.expect("1 error") self.flush(child)
def test_pdb_without_capture(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pytest def test_1(): pytest.set_trace() """) child = pytester.spawn_pytest("-s %s" % p1) child.expect(r">>> PDB set_trace >>>") child.expect("Pdb") child.sendline("c") child.expect(r">>> PDB continue >>>") child.expect("1 passed") self.flush(child)
def test_sys_breakpoint_interception(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" def test_1(): breakpoint() """) child = pytester.spawn_pytest(str(p1)) child.expect("test_1") child.expect("Pdb") child.sendline("quit") rest = child.read().decode("utf8") assert "Quitting debugger" in rest assert "reading from stdin while output" not in rest TestPDB.flush(child)
def test_pdb_dont_print_empty_captured_stdout_and_stderr( self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" def test_1(): assert False """) child = pytester.spawn_pytest("--pdb %s" % p1) child.expect("Pdb") output = child.before.decode("utf8") child.sendeof() assert "captured stdout" not in output assert "captured stderr" not in output self.flush(child)
def test_pdb_used_in_generate_tests(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pytest def pytest_generate_tests(metafunc): pytest.set_trace() x = 5 def test_foo(a): pass """) child = pytester.spawn_pytest(str(p1)) child.expect("x = 5") child.expect("Pdb") child.sendeof() self.flush(child)
def test_pdb_unittest_skip(self, pytester: Pytester) -> None: """Test for issue #2137""" p1 = pytester.makepyfile(""" import unittest @unittest.skipIf(True, 'Skipping also with pdb active') class MyTestCase(unittest.TestCase): def test_one(self): assert 0 """) child = pytester.spawn_pytest(f"-rs --pdb {p1}") child.expect("Skipping also with pdb active") child.expect_exact("= 1 skipped in") child.sendeof() self.flush(child)
def test_pdb_and_capsys(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pytest def test_1(capsys): print("hello1") pytest.set_trace() """) child = pytester.spawn_pytest(str(p1)) child.expect("test_1") child.send("capsys.readouterr()\n") child.expect("hello1") child.sendeof() child.read() self.flush(child)
def test_pdb_not_altered(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pdb def test_1(): pdb.set_trace() assert 0 """) child = pytester.spawn_pytest(str(p1)) child.expect("test_1") child.expect("Pdb") child.sendline("c") rest = child.read().decode("utf8") assert "1 failed" in rest assert "reading from stdin while output" not in rest TestPDB.flush(child)
def test_pdb_with_caplog_on_pdb_invocation(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" def test_1(capsys, caplog): import logging logging.getLogger(__name__).warning("some_warning") assert 0 """) child = pytester.spawn_pytest("--pdb %s" % str(p1)) child.send("caplog.record_tuples\n") child.expect_exact( "[('test_pdb_with_caplog_on_pdb_invocation', 30, 'some_warning')]") child.sendeof() child.read() self.flush(child)
def test_pdb_set_trace_interception(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pdb def test_1(): pdb.set_trace() """) child = pytester.spawn_pytest(str(p1)) child.expect("test_1") child.expect("Pdb") child.sendline("q") rest = child.read().decode("utf8") assert "no tests ran" in rest assert "reading from stdin while output" not in rest assert "BdbQuit" not in rest self.flush(child)
def test_spawn_uses_tmphome(pytester: Pytester) -> None: tmphome = str(pytester.path) assert os.environ.get("HOME") == tmphome pytester._monkeypatch.setenv("CUSTOMENV", "42") p1 = pytester.makepyfile(""" import os def test(): assert os.environ["HOME"] == {tmphome!r} assert os.environ["CUSTOMENV"] == "42" """.format(tmphome=tmphome)) child = pytester.spawn_pytest(str(p1)) out = child.read() assert child.wait() == 0, out.decode("utf8")
def test_pdb_unittest_postmortem(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import unittest class Blub(unittest.TestCase): def tearDown(self): self.filename = None def test_false(self): self.filename = 'debug' + '.me' assert 0 """) child = pytester.spawn_pytest(f"--pdb {p1}") child.expect("Pdb") child.sendline("p self.filename") child.sendeof() rest = child.read().decode("utf8") assert "debug.me" in rest self.flush(child)
def test_pdb_interaction_exception(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pytest def globalfunc(): pass def test_1(): pytest.raises(ValueError, globalfunc) """) child = pytester.spawn_pytest("--pdb %s" % p1) child.expect(".*def test_1") child.expect(".*pytest.raises.*globalfunc") child.expect("Pdb") child.sendline("globalfunc") child.expect(".*function") child.sendeof() child.expect("1 failed") self.flush(child)
def test_doctest_set_trace_quit(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" def function_1(): ''' >>> __import__('pdb').set_trace() ''' """) # NOTE: does not use pytest.set_trace, but Python's patched pdb, # therefore "-s" is required. child = pytester.spawn_pytest("--doctest-modules --pdb -s %s" % p1) child.expect("Pdb") child.sendline("q") rest = child.read().decode("utf8") assert "! _pytest.outcomes.Exit: Quitting debugger !" in rest assert "= no tests ran in" in rest assert "BdbQuit" not in rest assert "UNEXPECTED EXCEPTION" not in rest
def test_pdb_interaction_on_internal_error(self, pytester: Pytester) -> None: pytester.makeconftest(""" def pytest_runtest_protocol(): 0/0 """) p1 = pytester.makepyfile("def test_func(): pass") child = pytester.spawn_pytest("--pdb %s" % p1) child.expect("Pdb") # INTERNALERROR is only displayed once via terminal reporter. assert (len([ x for x in child.before.decode().splitlines() if x.startswith("INTERNALERROR> Traceback") ]) == 1) child.sendeof() self.flush(child)
def test_pdb_print_captured_logs_nologging(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" def test_1(): import logging logging.warn("get " + "rekt") assert False """) child = pytester.spawn_pytest( "--show-capture=all --pdb -p no:logging %s" % p1) child.expect("get rekt") output = child.before.decode("utf8") assert "captured log" not in output child.expect("Pdb") child.sendeof() rest = child.read().decode("utf8") assert "1 failed" in rest self.flush(child)
def test_set_trace_capturing_afterwards(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pdb def test_1(): pdb.set_trace() def test_2(): print("hello") assert 0 """) child = pytester.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() self.flush(child)
def test_trace_with_parametrize_handles_shared_fixtureinfo( self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pytest @pytest.mark.parametrize('myparam', [1,2]) def test_1(myparam, request): assert myparam in (1, 2) assert request.function.__name__ == "test_1" @pytest.mark.parametrize('func', [1,2]) def test_func(func, request): assert func in (1, 2) assert request.function.__name__ == "test_func" @pytest.mark.parametrize('myparam', [1,2]) def test_func_kw(myparam, request, func="func_kw"): assert myparam in (1, 2) assert func == "func_kw" assert request.function.__name__ == "test_func_kw" """) child = pytester.spawn_pytest("--trace " + str(p1)) for func, argname in [ ("test_1", "myparam"), ("test_func", "func"), ("test_func_kw", "myparam"), ]: child.expect_exact("> PDB runcall (IO-capturing turned off) >") child.expect_exact(func) child.expect_exact("Pdb") child.sendline("args") child.expect_exact(f"{argname} = 1\r\n") child.expect_exact("Pdb") child.sendline("c") child.expect_exact("Pdb") child.sendline("args") child.expect_exact(f"{argname} = 2\r\n") child.expect_exact("Pdb") child.sendline("c") child.expect_exact("> PDB continue (IO-capturing resumed) >") rest = child.read().decode("utf8") assert "= 6 passed in" in rest assert "reading from stdin while output" not in rest # Only printed once - not on stderr. assert "Exit: Quitting debugger" not in child.before.decode("utf8") TestPDB.flush(child)
def test_pdb_suspends_fixture_capturing(pytester: Pytester, fixture: str) -> None: """Using "-s" with pytest should suspend/resume fixture capturing.""" p1 = pytester.makepyfile(""" def test_inner({fixture}): import sys print("out_inner_before") sys.stderr.write("err_inner_before\\n") __import__("pdb").set_trace() print("out_inner_after") sys.stderr.write("err_inner_after\\n") out, err = {fixture}.readouterr() assert out =="out_inner_before\\nout_inner_after\\n" assert err =="err_inner_before\\nerr_inner_after\\n" """.format(fixture=fixture)) child = pytester.spawn_pytest(str(p1) + " -s") child.expect("Pdb") before = child.before.decode("utf8") assert ("> PDB set_trace (IO-capturing turned off for fixture %s) >" % (fixture) in before) # Test that capturing is really suspended. child.sendline("p 40 + 2") child.expect("Pdb") assert "\r\n42\r\n" in child.before.decode("utf8") child.sendline("c") rest = child.read().decode("utf8") assert "out_inner" not in rest assert "err_inner" not in rest TestPDB.flush(child) assert child.exitstatus == 0 assert "= 1 passed in" in rest assert "> PDB continue (IO-capturing resumed for fixture %s) >" % ( fixture) in rest
def test_pdb_set_trace_kwargs(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pytest def test_1(): i = 0 print("hello17") pytest.set_trace(header="== my_header ==") x = 3 assert 0 """) child = pytester.spawn_pytest(str(p1)) child.expect("== my_header ==") assert "PDB set_trace" not in child.before.decode() child.expect("Pdb") child.sendline("c") rest = child.read().decode("utf-8") assert "1 failed" in rest assert "def test_1" in rest assert "hello17" in rest # out is captured self.flush(child)
def test_pdb_interaction_capturing_simple(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" import pytest def test_1(): i = 0 print("hello17") pytest.set_trace() i == 1 assert 0 """) child = pytester.spawn_pytest(str(p1)) child.expect(r"test_1\(\)") child.expect("i == 1") child.expect("Pdb") child.sendline("c") rest = child.read().decode("utf-8") assert "AssertionError" in rest assert "1 failed" in rest assert "def test_1" in rest assert "hello17" in rest # out is captured self.flush(child)
def test_quit_with_swallowed_SystemExit(pytester: Pytester) -> None: """Test that debugging's pytest_configure is re-entrant.""" p1 = pytester.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 = pytester.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)
def test_pdb_interaction_doctest(self, pytester: Pytester) -> None: p1 = pytester.makepyfile(""" def function_1(): ''' >>> i = 0 >>> assert i == 1 ''' """) child = pytester.spawn_pytest("--doctest-modules --pdb %s" % p1) child.expect("Pdb") assert "UNEXPECTED EXCEPTION: AssertionError()" in child.before.decode( "utf8") child.sendline("'i=%i.' % i") child.expect("Pdb") assert "\r\n'i=0.'\r\n" in child.before.decode("utf8") child.sendeof() rest = child.read().decode("utf8") assert "! _pytest.outcomes.Exit: Quitting debugger !" in rest assert "BdbQuit" not in rest assert "1 failed" in rest self.flush(child)
def test_pdb_continue_with_recursive_debug(self, capture_arg, pytester: Pytester) -> None: """Full coverage for do_debug without capturing. This is very similar to test_pdb_interaction_continue_recursive in general, but mocks out ``pdb.set_trace`` for providing more coverage. """ p1 = pytester.makepyfile(""" try: input = raw_input except NameError: pass def set_trace(): __import__('pdb').set_trace() def test_1(monkeypatch): import _pytest.debugging class pytestPDBTest(_pytest.debugging.pytestPDB): @classmethod def set_trace(cls, *args, **kwargs): # Init PytestPdbWrapper to handle capturing. _pdb = cls._init_pdb("set_trace", *args, **kwargs) # Mock out pdb.Pdb.do_continue. import pdb pdb.Pdb.do_continue = lambda self, arg: None print("===" + " SET_TRACE ===") assert input() == "debug set_trace()" # Simulate PytestPdbWrapper.do_debug cls._recursive_debug += 1 print("ENTERING RECURSIVE DEBUGGER") print("===" + " SET_TRACE_2 ===") assert input() == "c" _pdb.do_continue("") print("===" + " SET_TRACE_3 ===") # Simulate PytestPdbWrapper.do_debug print("LEAVING RECURSIVE DEBUGGER") cls._recursive_debug -= 1 print("===" + " SET_TRACE_4 ===") assert input() == "c" _pdb.do_continue("") def do_continue(self, arg): print("=== do_continue") monkeypatch.setattr(_pytest.debugging, "pytestPDB", pytestPDBTest) import pdb monkeypatch.setattr(pdb, "set_trace", pytestPDBTest.set_trace) set_trace() """) child = pytester.spawn_pytest(f"--tb=short {p1} {capture_arg}") child.expect("=== SET_TRACE ===") before = child.before.decode("utf8") if not capture_arg: assert ">>> PDB set_trace (IO-capturing turned off) >>>" in before else: assert ">>> PDB set_trace >>>" in before child.sendline("debug set_trace()") child.expect("=== SET_TRACE_2 ===") before = child.before.decode("utf8") assert "\r\nENTERING RECURSIVE DEBUGGER\r\n" in before child.sendline("c") child.expect("=== SET_TRACE_3 ===") # No continue message with recursive debugging. before = child.before.decode("utf8") assert ">>> PDB continue " not in before child.sendline("c") child.expect("=== SET_TRACE_4 ===") before = child.before.decode("utf8") assert "\r\nLEAVING RECURSIVE DEBUGGER\r\n" in before child.sendline("c") rest = child.read().decode("utf8") if not capture_arg: assert "> PDB continue (IO-capturing resumed) >" in rest else: assert "> PDB continue >" in rest assert "= 1 passed in" in rest