def test_basic(self, testdir, hook: AssertionRewritingHook) -> None: """ Ensure we avoid calling PathFinder.find_spec when we know for sure a certain module will not be rewritten to optimize assertion rewriting (#3918). """ testdir.makeconftest( """ import pytest @pytest.fixture def fix(): return 1 """ ) testdir.makepyfile(test_foo="def test_foo(): pass") testdir.makepyfile(bar="def bar(): pass") foobar_path = testdir.makepyfile(foobar="def foobar(): pass") self.initial_paths.add(foobar_path) # conftest files should always be rewritten assert hook.find_spec("conftest") is not None assert self.find_spec_calls == ["conftest"] # files matching "python_files" mask should always be rewritten assert hook.find_spec("test_foo") is not None assert self.find_spec_calls == ["conftest", "test_foo"] # file does not match "python_files": early bailout assert hook.find_spec("bar") is None assert self.find_spec_calls == ["conftest", "test_foo"] # file is an initial path (passed on the command-line): should be rewritten assert hook.find_spec("foobar") is not None assert self.find_spec_calls == ["conftest", "test_foo", "foobar"]
def test_rewrite_infinite_recursion(testdir, pytestconfig, monkeypatch): """Fix infinite recursion when writing pyc files: if an import happens to be triggered when writing the pyc file, this would cause another call to the hook, which would trigger another pyc writing, which could trigger another import, and so on. (#3506)""" from _pytest.assertion import rewrite testdir.syspathinsert() testdir.makepyfile(test_foo="def test_foo(): pass") testdir.makepyfile(test_bar="def test_bar(): pass") original_write_pyc = rewrite._write_pyc write_pyc_called = [] def spy_write_pyc(*args, **kwargs): # make a note that we have called _write_pyc write_pyc_called.append(True) # try to import a module at this point: we should not try to rewrite this module assert hook.find_spec("test_bar") is None return original_write_pyc(*args, **kwargs) monkeypatch.setattr(rewrite, "_write_pyc", spy_write_pyc) monkeypatch.setattr(sys, "dont_write_bytecode", False) hook = AssertionRewritingHook(pytestconfig) spec = hook.find_spec("test_foo") assert spec is not None module = importlib.util.module_from_spec(spec) hook.exec_module(module) assert len(write_pyc_called) == 1
def test_remember_rewritten_modules(self, pytestconfig, testdir, monkeypatch): """`AssertionRewriteHook` should remember rewritten modules so it doesn't give false positives (#2005).""" monkeypatch.syspath_prepend(testdir.tmpdir) testdir.makepyfile(test_remember_rewritten_modules="") warnings = [] hook = AssertionRewritingHook(pytestconfig) monkeypatch.setattr( hook, "_warn_already_imported", lambda code, msg: warnings.append(msg) ) spec = hook.find_spec("test_remember_rewritten_modules") assert spec is not None module = importlib.util.module_from_spec(spec) hook.exec_module(module) hook.mark_rewrite("test_remember_rewritten_modules") hook.mark_rewrite("test_remember_rewritten_modules") assert warnings == []
def test_pattern_contains_subdirectories( self, testdir, hook: AssertionRewritingHook) -> None: """If one of the python_files patterns contain subdirectories ("tests/**.py") we can't bailout early because we need to match with the full path, which can only be found by calling PathFinder.find_spec """ p = testdir.makepyfile( **{ "tests/file.py": """\ def test_simple_failure(): assert 1 + 1 == 3 """ }) testdir.syspathinsert(p.dirpath()) hook.fnpats[:] = ["tests/**.py"] assert hook.find_spec("file") is not None assert self.find_spec_calls == ["file"]
def test_remember_rewritten_modules_warnings_stack_level( self, pytestconfig, testdir, monkeypatch): """ AssertionRewriteHook should raise warning with expected stack level """ def mock__issue_warning_captured(warning, hook, stacklevel=0): assert 5 == stacklevel monkeypatch.syspath_prepend(testdir.tmpdir) monkeypatch.setattr(_pytest.warnings, "_issue_warning_captured", mock__issue_warning_captured) testdir.makepyfile(test_remember_rewritten_modules="") hook = AssertionRewritingHook(pytestconfig) spec = hook.find_spec("test_remember_rewritten_modules") module = importlib.util.module_from_spec(spec) hook.exec_module(module) hook.mark_rewrite(*{"builtins": "<module 'builtins' (built-in)>"})