def test_pdb_teardown_skipped(pytester: Pytester, monkeypatch: MonkeyPatch, mark: str) -> None: """With --pdb, setUp and tearDown should not be called for skipped tests.""" tracked: List[str] = [] monkeypatch.setattr(pytest, "test_pdb_teardown_skipped", tracked, raising=False) pytester.makepyfile(""" import unittest import pytest class MyTestCase(unittest.TestCase): def setUp(self): pytest.test_pdb_teardown_skipped.append("setUp:" + self.id()) def tearDown(self): pytest.test_pdb_teardown_skipped.append("tearDown:" + self.id()) {mark}("skipped for reasons") def test_1(self): pass """.format(mark=mark)) result = pytester.runpytest_inprocess("--pdb") result.stdout.fnmatch_lines("* 1 skipped in *") assert tracked == []
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 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]
def test_current_test_env_var(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: pytest_current_test_vars: List[Tuple[str, str]] = [] monkeypatch.setattr(sys, "pytest_current_test_vars", pytest_current_test_vars, raising=False) pytester.makepyfile(""" import pytest import sys import os @pytest.fixture def fix(): sys.pytest_current_test_vars.append(('setup', os.environ['PYTEST_CURRENT_TEST'])) yield sys.pytest_current_test_vars.append(('teardown', os.environ['PYTEST_CURRENT_TEST'])) def test(fix): sys.pytest_current_test_vars.append(('call', os.environ['PYTEST_CURRENT_TEST'])) """) result = pytester.runpytest_inprocess() assert result.ret == 0 test_id = "test_current_test_env_var.py::test" assert pytest_current_test_vars == [ ("setup", test_id + " (setup)"), ("call", test_id + " (call)"), ("teardown", test_id + " (teardown)"), ] assert "PYTEST_CURRENT_TEST" not in os.environ
def test_pdb_teardown_called(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: """Ensure tearDown() is always called when --pdb is given in the command-line. We delay the normal tearDown() calls when --pdb is given, so this ensures we are calling tearDown() eventually to avoid memory leaks when using --pdb. """ teardowns: List[str] = [] monkeypatch.setattr(pytest, "test_pdb_teardown_called_teardowns", teardowns, raising=False) pytester.makepyfile(""" import unittest import pytest class MyTestCase(unittest.TestCase): def tearDown(self): pytest.test_pdb_teardown_called_teardowns.append(self.id()) def test_1(self): pass def test_2(self): pass """) result = pytester.runpytest_inprocess("--pdb") result.stdout.fnmatch_lines("* 2 passed in *") assert teardowns == [ "test_pdb_teardown_called.MyTestCase.test_1", "test_pdb_teardown_called.MyTestCase.test_2", ]
def test_clean_up(pytester: Pytester) -> None: """Test that the plugin cleans up after itself.""" # This is tough to test behaviorly because the cleanup really runs last. # So the test make several implementation assumptions: # - Cleanup is done in pytest_unconfigure(). # - Not a hookwrapper. # So we can add a hookwrapper ourselves to test what it does. pytester.makefile(".ini", pytest="[pytest]\npythonpath=I_SHALL_BE_REMOVED\n") pytester.makepyfile(test_foo="""def test_foo(): pass""") before: Optional[List[str]] = None after: Optional[List[str]] = None class Plugin: @pytest.hookimpl(hookwrapper=True, tryfirst=True) def pytest_unconfigure(self) -> Generator[None, None, None]: nonlocal before, after before = sys.path.copy() yield after = sys.path.copy() result = pytester.runpytest_inprocess(plugins=[Plugin()]) assert result.ret == 0 assert before is not None assert after is not None assert any("I_SHALL_BE_REMOVED" in entry for entry in before) assert not any("I_SHALL_BE_REMOVED" in entry for entry in after)
def test_calls_show_2(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("--durations=2") assert result.ret == 0 lines = result.stdout.get_lines_after("*slowest*durations*") assert "4 passed" in lines[2]
def test_early_load_setuptools_name( self, pytester: Pytester, monkeypatch, load_cov_early ) -> None: monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD") pytester.makepyfile(mytestplugin1_module="") pytester.makepyfile(mytestplugin2_module="") pytester.makepyfile(mycov_module="") pytester.syspathinsert() loaded = [] @attr.s class DummyEntryPoint: name = attr.ib() module = attr.ib() group = "pytest11" def load(self): __import__(self.module) loaded.append(self.name) return sys.modules[self.module] entry_points = [ DummyEntryPoint("myplugin1", "mytestplugin1_module"), DummyEntryPoint("myplugin2", "mytestplugin2_module"), DummyEntryPoint("mycov", "mycov_module"), ] @attr.s class DummyDist: entry_points = attr.ib() files = () def my_dists(): return (DummyDist(entry_points),) monkeypatch.setattr(importlib_metadata, "distributions", my_dists) params = ("-p", "mycov") if load_cov_early else () pytester.runpytest_inprocess(*params) if load_cov_early: assert loaded == ["mycov", "myplugin1", "myplugin2"] else: assert loaded == ["myplugin1", "myplugin2", "mycov"]
def test_pdb_custom_cls(self, pytester: Pytester, custom_debugger_hook) -> None: p1 = pytester.makepyfile(""" def test_nothing(): breakpoint() """) result = pytester.runpytest_inprocess( "--pdb", "--pdbcls=_pytest:_CustomDebugger", p1) result.stdout.fnmatch_lines(["*CustomDebugger*", "*1 passed*"]) assert custom_debugger_hook == ["init", "set_trace"]
def test_executable_path_commandoption(pytester: Pytester): testcase_path = pytester.makepyfile(""" def test_executable_path(executable_path, default_executable_path): assert executable_path != default_executable_path assert executable_path == "path/to/chrome" """) result = pytester.runpytest_inprocess(testcase_path, "--executable-path", "path/to/chrome") result.assert_outcomes(passed=1)
def test_setup_function(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("--durations=10") assert result.ret == 0 result.stdout.fnmatch_lines_random(""" *durations* 5.00s call *test_1* 2.00s setup *test_1* """)
def test_with_failing_collection(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) pytester.makepyfile(test_collecterror="""xyz""") result = pytester.runpytest_inprocess("--durations=2", "-k test_1") assert result.ret == 2 result.stdout.fnmatch_lines(["*Interrupted: 1 error during collection*"]) # Collection errors abort test execution, therefore no duration is # output result.stdout.no_fnmatch_line("*duration*")
def test_calls(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("--durations=10") assert result.ret == 0 result.stdout.fnmatch_lines_random( ["*durations*", "*call*test_3*", "*call*test_2*"]) result.stdout.fnmatch_lines([ "(8 durations < 0.005s hidden. Use -vv to show these durations.)" ])
def test_calls_showall_verbose(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("--durations=0", "-vv") assert result.ret == 0 for x in "123": for y in ("call",): # 'setup', 'call', 'teardown': for line in result.stdout.lines: if ("test_%s" % x) in line and y in line: break else: raise AssertionError(f"not found {x} {y}")
def test_options_updating(pytester: Pytester): testcase_path = pytester.makepyfile(""" import pytest @pytest.mark.options(devtools=True, headless=True) def test_options(options): assert options["devtools"] is True assert options["headless"] is True """) result = pytester.runpytest_inprocess(testcase_path) result.assert_outcomes(passed=1)
def test_pytester_subprocess_via_runpytest_arg(pytester: Pytester) -> None: testfile = pytester.makepyfile(""" def test_pytester_subprocess(pytester): import os testfile = pytester.makepyfile( \""" import os def test_one(): assert {} != os.getpid() \""".format(os.getpid()) ) assert pytester.runpytest(testfile).ret == 0 """) result = pytester.runpytest_inprocess("-p", "pytester", "--runpytest", "subprocess", testfile) assert result.ret == 0
def test_args_commandoption(pytester: Pytester): testcase_path = pytester.makepyfile(""" def test_args(args): assert args == ["--proxy-server=localhost:5555,direct://", "--proxy-bypass-list=192.0.0.1/8;10.0.0.1/8"] """) result = pytester.runpytest_inprocess( testcase_path, "--args", "proxy-server", "localhost:5555,direct://", "--args", "proxy-bypass-list", "192.0.0.1/8;10.0.0.1/8", ) result.assert_outcomes(passed=1)
def test_function_item_obj_is_instance(pytester: Pytester) -> None: """item.obj should be a bound method on unittest.TestCase function items (#5390).""" pytester.makeconftest(""" def pytest_runtest_makereport(item, call): if call.when == 'call': class_ = item.parent.obj assert isinstance(item.obj.__self__, class_) """) pytester.makepyfile(""" import unittest class Test(unittest.TestCase): def test_foo(self): pass """) result = pytester.runpytest_inprocess() result.stdout.fnmatch_lines(["* 1 passed in*"])
def test_platform_unknown(pytester: Pytester): pytester.makeconftest(""" import pytest @pytest.fixture(scope="session") def platform(): return "unknown" """) testcase_path = pytester.makepyfile(""" def test_default_executable_path(default_executable_path): assert default_executable_path is None def test_executable_path(executable_path): assert executable_path is None """) result = pytester.runpytest_inprocess(testcase_path) result.assert_outcomes(passed=2)
def test_clean_up_pythonpath(pytester: Pytester) -> None: """Test that the srcpaths plugin cleans up after itself.""" pytester.makefile(".ini", pytest="[pytest]\npythonpath=I_SHALL_BE_REMOVED\n") pytester.makepyfile(test_foo="""def test_foo(): pass""") before: Optional[List[str]] = None after: Optional[List[str]] = None class Plugin: @pytest.hookimpl(hookwrapper=True, tryfirst=True) def pytest_unconfigure(self) -> Generator[None, None, None]: nonlocal before, after before = sys.path.copy() yield after = sys.path.copy() result = pytester.runpytest_inprocess(plugins=[Plugin()]) assert result.ret == 0 assert before is not None assert after is not None assert any("I_SHALL_BE_REMOVED" in entry for entry in before) assert not any("I_SHALL_BE_REMOVED" in entry for entry in after)
def test_with_not(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("-k not 1") assert result.ret == 0
def test_with_deselected(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("--durations=2", "-k test_3") assert result.ret == 0 result.stdout.fnmatch_lines(["*durations*", "*call*test_3*"])
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'" ])