Пример #1
0
    def hook(self, pytestconfig, monkeypatch, testdir):
        """Returns a patched AssertionRewritingHook instance so we can configure its initial paths and track
        if PathFinder.find_spec has been called.
        """
        import importlib.machinery

        self.find_spec_calls = []
        self.initial_paths = set()

        class StubSession:
            _initialpaths = self.initial_paths

            def isinitpath(self, p):
                return p in self._initialpaths

        def spy_find_spec(name, path):
            self.find_spec_calls.append(name)
            return importlib.machinery.PathFinder.find_spec(name, path)

        hook = AssertionRewritingHook(pytestconfig)
        # use default patterns, otherwise we inherit pytest's testing config
        hook.fnpats[:] = ["test_*.py", "*_test.py"]
        monkeypatch.setattr(hook, "_find_spec", spy_find_spec)
        hook.set_session(StubSession())
        testdir.syspathinsert()
        return hook
Пример #2
0
    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"]
Пример #3
0
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
Пример #4
0
    def run(source_code_or_function, rewrite_assertions=True):
        """
        Create module object, execute it and return
        Can be used as a decorator of the function from the source code of which the module will be constructed

        :param source_code_or_function string or function with body as a source code for created module
        :param rewrite_assertions: whether to rewrite assertions in module or not

        """
        if isinstance(source_code_or_function, FunctionType):
            source_code = _extract_source_code_from_function(source_code_or_function)
        else:
            source_code = source_code_or_function

        module_name, filename = _create_module_file(source_code, tmp_path, request.node.name)

        if rewrite_assertions:
            loader = AssertionRewritingHook(config=request.config)
            loader.mark_rewrite(module_name)
        else:
            loader = None

        spec = importlib.util.spec_from_file_location(module_name, filename, loader=loader)
        sys.modules[module_name] = module = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(module)
        return module
Пример #5
0
    def hook(self, pytestconfig, monkeypatch, testdir):
        """Returns a patched AssertionRewritingHook instance so we can configure its initial paths and track
        if imp.find_module has been called.
        """
        import imp

        self.find_module_calls = []
        self.initial_paths = set()

        class StubSession(object):
            _initialpaths = self.initial_paths

            def isinitpath(self, p):
                return p in self._initialpaths

        def spy_imp_find_module(name, path):
            self.find_module_calls.append(name)
            return imp.find_module(name, path)

        hook = AssertionRewritingHook(pytestconfig)
        # use default patterns, otherwise we inherit pytest's testing config
        hook.fnpats[:] = ["test_*.py", "*_test.py"]
        monkeypatch.setattr(hook, "_imp_find_module", spy_imp_find_module)
        hook.set_session(StubSession())
        testdir.syspathinsert()
        return hook
Пример #6
0
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_module("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)
    assert hook.find_module("test_foo") is not None
    assert len(write_pyc_called) == 1
Пример #7
0
    def _import_execute(module_name: str,
                        source: str,
                        rewrite_assertions: bool = False):
        if rewrite_assertions:
            loader = AssertionRewritingHook(config=request.config)
            loader.mark_rewrite(module_name)
        else:
            loader = None

        example_bash_file = tmp_work_path / 'example.sh'
        example_bash_file.write_text('#!/bin/sh\necho testing')
        example_bash_file.chmod(0o755)
        (tmp_work_path / 'first/path').mkdir(parents=True, exist_ok=True)
        (tmp_work_path / 'second/path').mkdir(parents=True, exist_ok=True)

        module_path = tmp_work_path / f'{module_name}.py'
        module_path.write_text(source)
        spec = importlib.util.spec_from_file_location('__main__',
                                                      str(module_path),
                                                      loader=loader)
        module = importlib.util.module_from_spec(spec)
        try:
            spec.loader.exec_module(module)
        except KeyboardInterrupt:
            print('KeyboardInterrupt')
Пример #8
0
 def test_rewrite_warning(self, pytestconfig, monkeypatch):
     hook = AssertionRewritingHook(pytestconfig)
     warnings = []
     def mywarn(code, msg):
         warnings.append((code, msg))
     monkeypatch.setattr(hook.config, 'warn', mywarn)
     hook.mark_rewrite('_pytest')
     assert '_pytest' in warnings[0][1]
Пример #9
0
    def test_rewrite_warning(self, pytestconfig, monkeypatch):
        hook = AssertionRewritingHook(pytestconfig)
        warnings = []

        def mywarn(code, msg):
            warnings.append((code, msg))

        monkeypatch.setattr(hook.config, 'warn', mywarn)
        hook.mark_rewrite('_pytest')
        assert '_pytest' in warnings[0][1]
Пример #10
0
 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"]
Пример #11
0
 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.config, 'warn', lambda code, msg: warnings.append(msg))
     hook.find_module('test_remember_rewritten_modules')
     hook.load_module('test_remember_rewritten_modules')
     hook.mark_rewrite('test_remember_rewritten_modules')
     hook.mark_rewrite('test_remember_rewritten_modules')
     assert warnings == []
 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.config, 'warn', lambda code, msg: warnings.append(msg))
     hook.find_module('test_remember_rewritten_modules')
     hook.load_module('test_remember_rewritten_modules')
     hook.mark_rewrite('test_remember_rewritten_modules')
     hook.mark_rewrite('test_remember_rewritten_modules')
     assert warnings == []
Пример #13
0
 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 == []
Пример #14
0
    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)>"})