From 897f151e94ad4a16721510fbdbf935f8344aad0a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 25 Oct 2020 02:03:20 +0200 Subject: [PATCH] testing: use pytester.spawn instead of testdir Part of investigating a bug, but didn't fix it. --- testing/test_debugging.py | 354 +++++++++++++++++++++----------------- testing/test_pytester.py | 11 +- testing/test_terminal.py | 14 +- 3 files changed, 205 insertions(+), 174 deletions(-) diff --git a/testing/test_debugging.py b/testing/test_debugging.py index 2760930ef..ed96f7ec7 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -1,9 +1,12 @@ import os import sys +from typing import List import _pytest._code import pytest from _pytest.debugging import _validate_usepdb_cls +from _pytest.monkeypatch import MonkeyPatch +from _pytest.pytester import Pytester try: # Type ignored for Python <= 3.6. @@ -19,22 +22,22 @@ _ENVIRON_PYTHONBREAKPOINT = os.environ.get("PYTHONBREAKPOINT", "") @pytest.fixture(autouse=True) def pdb_env(request): - if "testdir" in request.fixturenames: + if "pytester" in request.fixturenames: # Disable pdb++ with inner tests. - testdir = request.getfixturevalue("testdir") - testdir.monkeypatch.setenv("PDBPP_HIJACK_PDB", "0") + pytester = request.getfixturevalue("testdir") + pytester.monkeypatch.setenv("PDBPP_HIJACK_PDB", "0") -def runpdb_and_get_report(testdir, source): - p = testdir.makepyfile(source) - result = testdir.runpytest_inprocess("--pdb", p) - reports = result.reprec.getreports("pytest_runtest_logreport") +def runpdb_and_get_report(pytester: Pytester, source: str): + p = pytester.makepyfile(source) + result = pytester.runpytest_inprocess("--pdb", p) + reports = result.reprec.getreports("pytest_runtest_logreport") # type: ignore[attr-defined] assert len(reports) == 3, reports # setup/call/teardown return reports[1] @pytest.fixture -def custom_pdb_calls(): +def custom_pdb_calls() -> List[str]: called = [] # install dummy debugger class and track which methods were called on it @@ -91,9 +94,9 @@ class TestPDB: monkeypatch.setattr(plugin, "post_mortem", mypdb) return pdblist - def test_pdb_on_fail(self, testdir, pdblist): + def test_pdb_on_fail(self, pytester: Pytester, pdblist) -> None: rep = runpdb_and_get_report( - testdir, + pytester, """ def test_func(): assert 0 @@ -104,9 +107,9 @@ class TestPDB: tb = _pytest._code.Traceback(pdblist[0][0]) assert tb[-1].name == "test_func" - def test_pdb_on_xfail(self, testdir, pdblist): + def test_pdb_on_xfail(self, pytester: Pytester, pdblist) -> None: rep = runpdb_and_get_report( - testdir, + pytester, """ import pytest @pytest.mark.xfail @@ -117,9 +120,9 @@ class TestPDB: assert "xfail" in rep.keywords assert not pdblist - def test_pdb_on_skip(self, testdir, pdblist): + def test_pdb_on_skip(self, pytester, pdblist) -> None: rep = runpdb_and_get_report( - testdir, + pytester, """ import pytest def test_func(): @@ -129,9 +132,9 @@ class TestPDB: assert rep.skipped assert len(pdblist) == 0 - def test_pdb_on_BdbQuit(self, testdir, pdblist): + def test_pdb_on_BdbQuit(self, pytester, pdblist) -> None: rep = runpdb_and_get_report( - testdir, + pytester, """ import bdb def test_func(): @@ -141,9 +144,9 @@ class TestPDB: assert rep.failed assert len(pdblist) == 0 - def test_pdb_on_KeyboardInterrupt(self, testdir, pdblist): + def test_pdb_on_KeyboardInterrupt(self, pytester, pdblist) -> None: rep = runpdb_and_get_report( - testdir, + pytester, """ def test_func(): raise KeyboardInterrupt @@ -160,8 +163,8 @@ class TestPDB: child.wait() assert not child.isalive() - def test_pdb_unittest_postmortem(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_unittest_postmortem(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import unittest class Blub(unittest.TestCase): @@ -172,7 +175,7 @@ class TestPDB: assert 0 """ ) - child = testdir.spawn_pytest("--pdb %s" % p1) + child = pytester.spawn_pytest(f"--pdb {p1}") child.expect("Pdb") child.sendline("p self.filename") child.sendeof() @@ -180,9 +183,9 @@ class TestPDB: assert "debug.me" in rest self.flush(child) - def test_pdb_unittest_skip(self, testdir): + def test_pdb_unittest_skip(self, pytester: Pytester) -> None: """Test for issue #2137""" - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( """ import unittest @unittest.skipIf(True, 'Skipping also with pdb active') @@ -191,14 +194,14 @@ class TestPDB: assert 0 """ ) - child = testdir.spawn_pytest("-rs --pdb %s" % p1) + 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_print_captured_stdout_and_stderr(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_print_captured_stdout_and_stderr(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ def test_1(): import sys @@ -210,7 +213,7 @@ class TestPDB: pass """ ) - child = testdir.spawn_pytest("--pdb %s" % p1) + child = pytester.spawn_pytest("--pdb %s" % p1) child.expect("captured stdout") child.expect("get rekt") child.expect("captured stderr") @@ -226,14 +229,16 @@ class TestPDB: assert "get rekt" not in rest self.flush(child) - def test_pdb_dont_print_empty_captured_stdout_and_stderr(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_dont_print_empty_captured_stdout_and_stderr( + self, pytester: Pytester + ) -> None: + p1 = pytester.makepyfile( """ def test_1(): assert False """ ) - child = testdir.spawn_pytest("--pdb %s" % p1) + child = pytester.spawn_pytest("--pdb %s" % p1) child.expect("Pdb") output = child.before.decode("utf8") child.sendeof() @@ -242,8 +247,8 @@ class TestPDB: self.flush(child) @pytest.mark.parametrize("showcapture", ["all", "no", "log"]) - def test_pdb_print_captured_logs(self, testdir, showcapture): - p1 = testdir.makepyfile( + def test_pdb_print_captured_logs(self, pytester, showcapture: str) -> None: + p1 = pytester.makepyfile( """ def test_1(): import logging @@ -251,7 +256,7 @@ class TestPDB: assert False """ ) - child = testdir.spawn_pytest(f"--show-capture={showcapture} --pdb {p1}") + child = pytester.spawn_pytest(f"--show-capture={showcapture} --pdb {p1}") if showcapture in ("all", "log"): child.expect("captured log") child.expect("get rekt") @@ -261,8 +266,8 @@ class TestPDB: assert "1 failed" in rest self.flush(child) - def test_pdb_print_captured_logs_nologging(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_print_captured_logs_nologging(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ def test_1(): import logging @@ -270,7 +275,7 @@ class TestPDB: assert False """ ) - child = testdir.spawn_pytest("--show-capture=all --pdb -p no:logging %s" % p1) + 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 @@ -280,8 +285,8 @@ class TestPDB: assert "1 failed" in rest self.flush(child) - def test_pdb_interaction_exception(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_interaction_exception(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pytest def globalfunc(): @@ -290,7 +295,7 @@ class TestPDB: pytest.raises(ValueError, globalfunc) """ ) - child = testdir.spawn_pytest("--pdb %s" % p1) + child = pytester.spawn_pytest("--pdb %s" % p1) child.expect(".*def test_1") child.expect(".*pytest.raises.*globalfunc") child.expect("Pdb") @@ -300,29 +305,29 @@ class TestPDB: child.expect("1 failed") self.flush(child) - def test_pdb_interaction_on_collection_issue181(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_interaction_on_collection_issue181(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pytest xxx """ ) - child = testdir.spawn_pytest("--pdb %s" % p1) + 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_interaction_on_internal_error(self, testdir): - testdir.makeconftest( + def test_pdb_interaction_on_internal_error(self, pytester: Pytester) -> None: + pytester.makeconftest( """ def pytest_runtest_protocol(): 0/0 """ ) - p1 = testdir.makepyfile("def test_func(): pass") - child = testdir.spawn_pytest("--pdb %s" % p1) + 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. @@ -340,17 +345,24 @@ class TestPDB: child.sendeof() self.flush(child) - def test_pdb_prevent_ConftestImportFailure_hiding_exception(self, testdir): - testdir.makepyfile("def test_func(): pass") - sub_dir = testdir.tmpdir.join("ns").ensure_dir() - sub_dir.join("conftest").new(ext=".py").write("import unknown") - sub_dir.join("test_file").new(ext=".py").write("def test_func(): pass") + def test_pdb_prevent_ConftestImportFailure_hiding_exception( + self, pytester: Pytester + ) -> None: + pytester.makepyfile("def test_func(): pass") + sub_dir = pytester.path.joinpath("ns") + sub_dir.mkdir() + sub_dir.joinpath("conftest").with_suffix(".py").write_text( + "import unknown", "utf-8" + ) + sub_dir.joinpath("test_file").with_suffix(".py").write_text( + "def test_func(): pass", "utf-8" + ) - result = testdir.runpytest_subprocess("--pdb", ".") + result = pytester.runpytest_subprocess("--pdb", ".") result.stdout.fnmatch_lines(["-> import unknown"]) - def test_pdb_interaction_capturing_simple(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_interaction_capturing_simple(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pytest def test_1(): @@ -361,7 +373,7 @@ class TestPDB: assert 0 """ ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) child.expect(r"test_1\(\)") child.expect("i == 1") child.expect("Pdb") @@ -373,8 +385,8 @@ class TestPDB: assert "hello17" in rest # out is captured self.flush(child) - def test_pdb_set_trace_kwargs(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_set_trace_kwargs(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pytest def test_1(): @@ -385,7 +397,7 @@ class TestPDB: assert 0 """ ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) child.expect("== my_header ==") assert "PDB set_trace" not in child.before.decode() child.expect("Pdb") @@ -396,15 +408,15 @@ class TestPDB: assert "hello17" in rest # out is captured self.flush(child) - def test_pdb_set_trace_interception(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_set_trace_interception(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pdb def test_1(): pdb.set_trace() """ ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) child.expect("test_1") child.expect("Pdb") child.sendline("q") @@ -414,8 +426,8 @@ class TestPDB: assert "BdbQuit" not in rest self.flush(child) - def test_pdb_and_capsys(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_and_capsys(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pytest def test_1(capsys): @@ -423,7 +435,7 @@ class TestPDB: pytest.set_trace() """ ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) child.expect("test_1") child.send("capsys.readouterr()\n") child.expect("hello1") @@ -431,8 +443,8 @@ class TestPDB: child.read() self.flush(child) - def test_pdb_with_caplog_on_pdb_invocation(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_with_caplog_on_pdb_invocation(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ def test_1(capsys, caplog): import logging @@ -440,7 +452,7 @@ class TestPDB: assert 0 """ ) - child = testdir.spawn_pytest("--pdb %s" % str(p1)) + 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')]" @@ -449,8 +461,8 @@ class TestPDB: child.read() self.flush(child) - def test_set_trace_capturing_afterwards(self, testdir): - p1 = testdir.makepyfile( + def test_set_trace_capturing_afterwards(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pdb def test_1(): @@ -460,7 +472,7 @@ class TestPDB: assert 0 """ ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) child.expect("test_1") child.send("c\n") child.expect("test_2") @@ -470,8 +482,8 @@ class TestPDB: child.read() self.flush(child) - def test_pdb_interaction_doctest(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_interaction_doctest(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ def function_1(): ''' @@ -480,7 +492,7 @@ class TestPDB: ''' """ ) - child = testdir.spawn_pytest("--doctest-modules --pdb %s" % p1) + child = pytester.spawn_pytest("--doctest-modules --pdb %s" % p1) child.expect("Pdb") assert "UNEXPECTED EXCEPTION: AssertionError()" in child.before.decode("utf8") @@ -496,8 +508,8 @@ class TestPDB: assert "1 failed" in rest self.flush(child) - def test_doctest_set_trace_quit(self, testdir): - p1 = testdir.makepyfile( + def test_doctest_set_trace_quit(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ def function_1(): ''' @@ -507,7 +519,7 @@ class TestPDB: ) # NOTE: does not use pytest.set_trace, but Python's patched pdb, # therefore "-s" is required. - child = testdir.spawn_pytest("--doctest-modules --pdb -s %s" % p1) + child = pytester.spawn_pytest("--doctest-modules --pdb -s %s" % p1) child.expect("Pdb") child.sendline("q") rest = child.read().decode("utf8") @@ -517,8 +529,8 @@ class TestPDB: assert "BdbQuit" not in rest assert "UNEXPECTED EXCEPTION" not in rest - def test_pdb_interaction_capturing_twice(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_interaction_capturing_twice(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pytest def test_1(): @@ -532,7 +544,7 @@ class TestPDB: assert 0 """ ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) child.expect(r"PDB set_trace \(IO-capturing turned off\)") child.expect("test_1") child.expect("x = 3") @@ -552,11 +564,11 @@ class TestPDB: assert "1 failed" in rest self.flush(child) - def test_pdb_with_injected_do_debug(self, testdir): + def test_pdb_with_injected_do_debug(self, pytester: Pytester) -> None: """Simulates pdbpp, which injects Pdb into do_debug, and uses self.__class__ in do_continue. """ - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( mytest=""" import pdb import pytest @@ -598,7 +610,7 @@ class TestPDB: pytest.fail("expected_failure") """ ) - child = testdir.spawn_pytest("--pdbcls=mytest:CustomPdb %s" % str(p1)) + child = pytester.spawn_pytest("--pdbcls=mytest:CustomPdb %s" % str(p1)) child.expect(r"PDB set_trace \(IO-capturing turned off\)") child.expect(r"\n\(Pdb") child.sendline("debug foo()") @@ -627,15 +639,15 @@ class TestPDB: assert "AssertionError: unexpected_failure" not in rest self.flush(child) - def test_pdb_without_capture(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_without_capture(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pytest def test_1(): pytest.set_trace() """ ) - child = testdir.spawn_pytest("-s %s" % p1) + child = pytester.spawn_pytest("-s %s" % p1) child.expect(r">>> PDB set_trace >>>") child.expect("Pdb") child.sendline("c") @@ -644,13 +656,15 @@ class TestPDB: self.flush(child) @pytest.mark.parametrize("capture_arg", ("", "-s", "-p no:capture")) - def test_pdb_continue_with_recursive_debug(self, capture_arg, testdir): + 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 = testdir.makepyfile( + p1 = pytester.makepyfile( """ try: input = raw_input @@ -704,7 +718,7 @@ class TestPDB: set_trace() """ ) - child = testdir.spawn_pytest(f"--tb=short {p1} {capture_arg}") + child = pytester.spawn_pytest(f"--tb=short {p1} {capture_arg}") child.expect("=== SET_TRACE ===") before = child.before.decode("utf8") if not capture_arg: @@ -734,22 +748,22 @@ class TestPDB: assert "> PDB continue >" in rest assert "= 1 passed in" in rest - def test_pdb_used_outside_test(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_used_outside_test(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pytest pytest.set_trace() x = 5 """ ) - child = testdir.spawn(f"{sys.executable} {p1}") + child = pytester.spawn(f"{sys.executable} {p1}") child.expect("x = 5") child.expect("Pdb") child.sendeof() self.flush(child) - def test_pdb_used_in_generate_tests(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_used_in_generate_tests(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pytest def pytest_generate_tests(metafunc): @@ -759,22 +773,24 @@ class TestPDB: pass """ ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) child.expect("x = 5") child.expect("Pdb") child.sendeof() self.flush(child) - def test_pdb_collection_failure_is_shown(self, testdir): - p1 = testdir.makepyfile("xxx") - result = testdir.runpytest_subprocess("--pdb", p1) + def test_pdb_collection_failure_is_shown(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile("xxx") + result = pytester.runpytest_subprocess("--pdb", p1) result.stdout.fnmatch_lines( ["E NameError: *xxx*", "*! *Exit: Quitting debugger !*"] # due to EOF ) @pytest.mark.parametrize("post_mortem", (False, True)) - def test_enter_leave_pdb_hooks_are_called(self, post_mortem, testdir): - testdir.makeconftest( + def test_enter_leave_pdb_hooks_are_called( + self, post_mortem, pytester: Pytester + ) -> None: + pytester.makeconftest( """ mypdb = None @@ -798,7 +814,7 @@ class TestPDB: assert mypdb.set_attribute == "bar" """ ) - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( """ import pytest @@ -811,9 +827,9 @@ class TestPDB: """ ) if post_mortem: - child = testdir.spawn_pytest(str(p1) + " --pdb -s -k test_post_mortem") + child = pytester.spawn_pytest(str(p1) + " --pdb -s -k test_post_mortem") else: - child = testdir.spawn_pytest(str(p1) + " -k test_set_trace") + child = pytester.spawn_pytest(str(p1) + " -k test_set_trace") child.expect("enter_pdb_hook") child.sendline("c") if post_mortem: @@ -826,14 +842,18 @@ class TestPDB: assert "1 failed" in rest self.flush(child) - def test_pdb_custom_cls(self, testdir, custom_pdb_calls): - p1 = testdir.makepyfile("""xxx """) - result = testdir.runpytest_inprocess("--pdb", "--pdbcls=_pytest:_CustomPdb", p1) + def test_pdb_custom_cls( + self, pytester: Pytester, custom_pdb_calls: List[str] + ) -> None: + p1 = pytester.makepyfile("""xxx """) + result = pytester.runpytest_inprocess( + "--pdb", "--pdbcls=_pytest:_CustomPdb", p1 + ) result.stdout.fnmatch_lines(["*NameError*xxx*", "*1 error*"]) assert custom_pdb_calls == ["init", "reset", "interaction"] - def test_pdb_custom_cls_invalid(self, testdir): - result = testdir.runpytest_inprocess("--pdbcls=invalid") + def test_pdb_custom_cls_invalid(self, pytester: Pytester) -> None: + result = pytester.runpytest_inprocess("--pdbcls=invalid") result.stderr.fnmatch_lines( [ "*: error: argument --pdbcls: 'invalid' is not in the format 'modname:classname'" @@ -848,14 +868,18 @@ class TestPDB: assert _validate_usepdb_cls("pdb:DoesNotExist") == ("pdb", "DoesNotExist") - def test_pdb_custom_cls_without_pdb(self, testdir, custom_pdb_calls): - p1 = testdir.makepyfile("""xxx """) - result = testdir.runpytest_inprocess("--pdbcls=_pytest:_CustomPdb", p1) + def test_pdb_custom_cls_without_pdb( + self, pytester: Pytester, custom_pdb_calls: List[str] + ) -> None: + p1 = pytester.makepyfile("""xxx """) + result = pytester.runpytest_inprocess("--pdbcls=_pytest:_CustomPdb", p1) result.stdout.fnmatch_lines(["*NameError*xxx*", "*1 error*"]) assert custom_pdb_calls == [] - def test_pdb_custom_cls_with_set_trace(self, testdir, monkeypatch): - testdir.makepyfile( + 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): @@ -868,7 +892,7 @@ class TestPDB: print('custom set_trace>') """ ) - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( """ import pytest @@ -876,8 +900,8 @@ class TestPDB: pytest.set_trace(skip=['foo.*']) """ ) - monkeypatch.setenv("PYTHONPATH", str(testdir.tmpdir)) - child = testdir.spawn_pytest("--pdbcls=custom_pdb:CustomPdb %s" % str(p1)) + 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>") @@ -885,7 +909,7 @@ class TestPDB: class TestDebuggingBreakpoints: - def test_supports_breakpoint_module_global(self): + def test_supports_breakpoint_module_global(self) -> None: """Test that supports breakpoint global marks on Python 3.7+.""" if sys.version_info >= (3, 7): assert SUPPORTS_BREAKPOINT_BUILTIN is True @@ -894,12 +918,14 @@ class TestDebuggingBreakpoints: not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin" ) @pytest.mark.parametrize("arg", ["--pdb", ""]) - def test_sys_breakpointhook_configure_and_unconfigure(self, testdir, arg): + def test_sys_breakpointhook_configure_and_unconfigure( + self, pytester: Pytester, arg: str + ) -> None: """ Test that sys.breakpointhook is set to the custom Pdb class once configured, test that hook is reset to system value once pytest has been unconfigured """ - testdir.makeconftest( + pytester.makeconftest( """ import sys from pytest import hookimpl @@ -915,26 +941,26 @@ class TestDebuggingBreakpoints: assert sys.breakpointhook == pytestPDB.set_trace """ ) - testdir.makepyfile( + pytester.makepyfile( """ def test_nothing(): pass """ ) args = (arg,) if arg else () - result = testdir.runpytest_subprocess(*args) + result = pytester.runpytest_subprocess(*args) result.stdout.fnmatch_lines(["*1 passed in *"]) @pytest.mark.skipif( not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin" ) - def test_pdb_custom_cls(self, testdir, custom_debugger_hook): - p1 = testdir.makepyfile( + def test_pdb_custom_cls(self, pytester: Pytester, custom_debugger_hook) -> None: + p1 = pytester.makepyfile( """ def test_nothing(): breakpoint() """ ) - result = testdir.runpytest_inprocess( + result = pytester.runpytest_inprocess( "--pdb", "--pdbcls=_pytest:_CustomDebugger", p1 ) result.stdout.fnmatch_lines(["*CustomDebugger*", "*1 passed*"]) @@ -944,8 +970,10 @@ class TestDebuggingBreakpoints: @pytest.mark.skipif( not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin" ) - def test_environ_custom_class(self, testdir, custom_debugger_hook, arg): - testdir.makeconftest( + def test_environ_custom_class( + self, pytester: Pytester, custom_debugger_hook, arg: str + ) -> None: + pytester.makeconftest( """ import os import sys @@ -963,13 +991,13 @@ class TestDebuggingBreakpoints: assert sys.breakpointhook is _pytest._CustomDebugger.set_trace """ ) - testdir.makepyfile( + pytester.makepyfile( """ def test_nothing(): pass """ ) args = (arg,) if arg else () - result = testdir.runpytest_subprocess(*args) + result = pytester.runpytest_subprocess(*args) result.stdout.fnmatch_lines(["*1 passed in *"]) @pytest.mark.skipif( @@ -979,14 +1007,14 @@ class TestDebuggingBreakpoints: not _ENVIRON_PYTHONBREAKPOINT == "", reason="Requires breakpoint() default value", ) - def test_sys_breakpoint_interception(self, testdir): - p1 = testdir.makepyfile( + def test_sys_breakpoint_interception(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ def test_1(): breakpoint() """ ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) child.expect("test_1") child.expect("Pdb") child.sendline("quit") @@ -998,8 +1026,8 @@ class TestDebuggingBreakpoints: @pytest.mark.skipif( not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin" ) - def test_pdb_not_altered(self, testdir): - p1 = testdir.makepyfile( + def test_pdb_not_altered(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ import pdb def test_1(): @@ -1007,7 +1035,7 @@ class TestDebuggingBreakpoints: assert 0 """ ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) child.expect("test_1") child.expect("Pdb") child.sendline("c") @@ -1018,8 +1046,8 @@ class TestDebuggingBreakpoints: class TestTraceOption: - def test_trace_sets_breakpoint(self, testdir): - p1 = testdir.makepyfile( + def test_trace_sets_breakpoint(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ def test_1(): assert True @@ -1031,7 +1059,7 @@ class TestTraceOption: pass """ ) - child = testdir.spawn_pytest("--trace " + str(p1)) + child = pytester.spawn_pytest("--trace " + str(p1)) child.expect("test_1") child.expect("Pdb") child.sendline("c") @@ -1049,8 +1077,10 @@ class TestTraceOption: assert "Exit: Quitting debugger" not in child.before.decode("utf8") TestPDB.flush(child) - def test_trace_with_parametrize_handles_shared_fixtureinfo(self, testdir): - p1 = testdir.makepyfile( + def test_trace_with_parametrize_handles_shared_fixtureinfo( + self, pytester: Pytester + ) -> None: + p1 = pytester.makepyfile( """ import pytest @pytest.mark.parametrize('myparam', [1,2]) @@ -1068,7 +1098,7 @@ class TestTraceOption: assert request.function.__name__ == "test_func_kw" """ ) - child = testdir.spawn_pytest("--trace " + str(p1)) + child = pytester.spawn_pytest("--trace " + str(p1)) for func, argname in [ ("test_1", "myparam"), ("test_func", "func"), @@ -1095,16 +1125,16 @@ class TestTraceOption: TestPDB.flush(child) -def test_trace_after_runpytest(testdir): +def test_trace_after_runpytest(pytester: Pytester) -> None: """Test that debugging's pytest_configure is re-entrant.""" - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( """ from _pytest.debugging import pytestPDB - def test_outer(testdir): + def test_outer(pytester) -> None: assert len(pytestPDB._saved) == 1 - testdir.makepyfile( + pytester.makepyfile( \""" from _pytest.debugging import pytestPDB @@ -1115,20 +1145,20 @@ def test_trace_after_runpytest(testdir): \""" ) - result = testdir.runpytest("-s", "-k", "test_inner") + result = pytester.runpytest("-s", "-k", "test_inner") assert result.ret == 0 assert len(pytestPDB._saved) == 1 """ ) - result = testdir.runpytest_subprocess("-s", "-p", "pytester", str(p1)) + result = pytester.runpytest_subprocess("-s", "-p", "pytester", str(p1)) result.stdout.fnmatch_lines(["test_inner_end"]) assert result.ret == 0 -def test_quit_with_swallowed_SystemExit(testdir): +def test_quit_with_swallowed_SystemExit(pytester: Pytester) -> None: """Test that debugging's pytest_configure is re-entrant.""" - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( """ def call_pdb_set_trace(): __import__('pdb').set_trace() @@ -1145,7 +1175,7 @@ def test_quit_with_swallowed_SystemExit(testdir): pass """ ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) child.expect("Pdb") child.sendline("q") child.expect_exact("Exit: Quitting debugger") @@ -1155,9 +1185,9 @@ def test_quit_with_swallowed_SystemExit(testdir): @pytest.mark.parametrize("fixture", ("capfd", "capsys")) -def test_pdb_suspends_fixture_capturing(testdir, fixture): +def test_pdb_suspends_fixture_capturing(pytester: Pytester, fixture: str) -> None: """Using "-s" with pytest should suspend/resume fixture capturing.""" - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( """ def test_inner({fixture}): import sys @@ -1178,7 +1208,7 @@ def test_pdb_suspends_fixture_capturing(testdir, fixture): ) ) - child = testdir.spawn_pytest(str(p1) + " -s") + child = pytester.spawn_pytest(str(p1) + " -s") child.expect("Pdb") before = child.before.decode("utf8") @@ -1203,9 +1233,9 @@ def test_pdb_suspends_fixture_capturing(testdir, fixture): assert "> PDB continue (IO-capturing resumed for fixture %s) >" % (fixture) in rest -def test_pdbcls_via_local_module(testdir): +def test_pdbcls_via_local_module(pytester: Pytester) -> None: """It should be imported in pytest_configure or later only.""" - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( """ def test(): print("before_set_trace") @@ -1221,7 +1251,7 @@ def test_pdbcls_via_local_module(testdir): print("runcall_called", args, kwds) """, ) - result = testdir.runpytest( + result = pytester.runpytest( str(p1), "--pdbcls=really.invalid:Value", syspathinsert=True ) result.stdout.fnmatch_lines( @@ -1232,24 +1262,24 @@ def test_pdbcls_via_local_module(testdir): ) assert result.ret == 1 - result = testdir.runpytest( + result = pytester.runpytest( str(p1), "--pdbcls=mypdb:Wrapped.MyPdb", syspathinsert=True ) assert result.ret == 0 result.stdout.fnmatch_lines(["*set_trace_called*", "* 1 passed in *"]) # Ensure that it also works with --trace. - result = testdir.runpytest( + result = pytester.runpytest( str(p1), "--pdbcls=mypdb:Wrapped.MyPdb", "--trace", syspathinsert=True ) assert result.ret == 0 result.stdout.fnmatch_lines(["*runcall_called*", "* 1 passed in *"]) -def test_raises_bdbquit_with_eoferror(testdir): +def test_raises_bdbquit_with_eoferror(pytester: Pytester) -> None: """It is not guaranteed that DontReadFromInput's read is called.""" - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( """ def input_without_read(*args, **kwargs): raise EOFError() @@ -1260,13 +1290,13 @@ def test_raises_bdbquit_with_eoferror(testdir): __import__('pdb').set_trace() """ ) - result = testdir.runpytest(str(p1)) + result = pytester.runpytest(str(p1)) result.stdout.fnmatch_lines(["E *BdbQuit", "*= 1 failed in*"]) assert result.ret == 1 -def test_pdb_wrapper_class_is_reused(testdir): - p1 = testdir.makepyfile( +def test_pdb_wrapper_class_is_reused(pytester: Pytester) -> None: + p1 = pytester.makepyfile( """ def test(): __import__("pdb").set_trace() @@ -1288,7 +1318,7 @@ def test_pdb_wrapper_class_is_reused(testdir): print("set_trace_called", args) """, ) - result = testdir.runpytest(str(p1), "--pdbcls=mypdb:MyPdb", syspathinsert=True) + result = pytester.runpytest(str(p1), "--pdbcls=mypdb:MyPdb", syspathinsert=True) assert result.ret == 0 result.stdout.fnmatch_lines( ["*set_trace_called*", "*set_trace_called*", "* 1 passed in *"] diff --git a/testing/test_pytester.py b/testing/test_pytester.py index fed201daf..457a62dd3 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -13,6 +13,7 @@ from _pytest.config import PytestPluginManager from _pytest.pytester import CwdSnapshot from _pytest.pytester import HookRecorder from _pytest.pytester import LineMatcher +from _pytest.pytester import Pytester from _pytest.pytester import SysModulesSnapshot from _pytest.pytester import SysPathsSnapshot from _pytest.pytester import Testdir @@ -707,13 +708,13 @@ def test_popen_default_stdin_stderr_and_stdin_None(testdir) -> None: assert result.ret == 0 -def test_spawn_uses_tmphome(testdir) -> None: - tmphome = str(testdir.tmpdir) +def test_spawn_uses_tmphome(pytester: Pytester) -> None: + tmphome = str(pytester.path) assert os.environ.get("HOME") == tmphome - testdir.monkeypatch.setenv("CUSTOMENV", "42") + pytester._monkeypatch.setenv("CUSTOMENV", "42") - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( """ import os @@ -724,7 +725,7 @@ def test_spawn_uses_tmphome(testdir) -> None: tmphome=tmphome ) ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) out = child.read() assert child.wait() == 0, out.decode("utf8") diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 490f2df09..77bd2ace6 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -133,23 +133,23 @@ class TestTerminal: ) linecomp.assert_contains_lines(["*test_show_runtest_logstart.py*"]) - def test_runtest_location_shown_before_test_starts(self, testdir): - testdir.makepyfile( + def test_runtest_location_shown_before_test_starts(self, pytester): + pytester.makepyfile( """ def test_1(): import time time.sleep(20) """ ) - child = testdir.spawn_pytest("") + child = pytester.spawn_pytest("") child.expect(".*test_runtest_location.*py") child.sendeof() child.kill(15) - def test_report_collect_after_half_a_second(self, testdir): + def test_report_collect_after_half_a_second(self, pytester, monkeypatch): """Test for "collecting" being updated after 0.5s""" - testdir.makepyfile( + pytester.makepyfile( **{ "test1.py": """ import _pytest.terminal @@ -163,9 +163,9 @@ class TestTerminal: } ) # Explicitly test colored output. - testdir.monkeypatch.setenv("PY_COLORS", "1") + monkeypatch.setenv("PY_COLORS", "1") - child = testdir.spawn_pytest("-v test1.py test2.py") + child = pytester.spawn_pytest("-v test1.py test2.py") child.expect(r"collecting \.\.\.") child.expect(r"collecting 1 item") child.expect(r"collecting 2 items")