From 5c8e5acf9d6d1ac03ed8a483acf329a3276c0622 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 17 Apr 2015 22:25:35 +0200 Subject: [PATCH] change test module importing behaviour to append to sys.path instead of prepending. This better allows to run test modules against installated versions of a package even if the package under test has the same import root. In this example:: testing/__init__.py testing/test_pkg_under_test.py pkg_under_test/ the tests will preferrably run against the installed version of pkg_under_test whereas before they would always pick up the local version. --HG-- branch : prefer_installed --- CHANGELOG | 13 +++++++++++++ _pytest/__init__.py | 2 +- _pytest/pytester.py | 6 ++---- _pytest/python.py | 3 ++- setup.py | 10 +++++----- testing/python/collect.py | 20 ++++++++++++++++++++ testing/python/integration.py | 4 ++-- testing/test_core.py | 1 + 8 files changed, 46 insertions(+), 13 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 53144b7d8..d1d31525e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,19 @@ 2.8.0.dev (compared to 2.7.X) ----------------------------- +- change test module importing behaviour to append to sys.path + instead of prepending. This better allows to run test modules + against installated versions of a package even if the package + under test has the same import root. In this example:: + + testing/__init__.py + testing/test_pkg_under_test.py + pkg_under_test/ + + the tests will preferrably run against the installed version + of pkg_under_test whereas before they would always pick + up the local version. Thanks Holger Krekel. + 2.7.1.dev (compared to 2.7.0) ----------------------------- diff --git a/_pytest/__init__.py b/_pytest/__init__.py index 5c9ad256f..81fca72a9 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '2.8.0.dev1' +__version__ = '2.8.0.dev2' diff --git a/_pytest/pytester.py b/_pytest/pytester.py index 1ab7ba2c6..f90a7b5ab 100644 --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -254,7 +254,7 @@ class TmpTestdir: break self.tmpdir = tmpdir self.plugins = [] - self._syspathremove = [] + self._savesyspath = list(sys.path) self.chdir() # always chdir self.request.addfinalizer(self.finalize) @@ -270,8 +270,7 @@ class TmpTestdir: has finished. """ - for p in self._syspathremove: - sys.path.remove(p) + sys.path[:] = self._savesyspath if hasattr(self, '_olddir'): self._olddir.chdir() # delete modules that have been loaded from tmpdir @@ -370,7 +369,6 @@ class TmpTestdir: if path is None: path = self.tmpdir sys.path.insert(0, str(path)) - self._syspathremove.append(str(path)) def mkdir(self, name): """Create a new (sub)directory.""" diff --git a/_pytest/python.py b/_pytest/python.py index 7dd4095b8..edbd5c823 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -485,7 +485,7 @@ class Module(pytest.File, PyCollector): def _importtestmodule(self): # we assume we are only called once per module try: - mod = self.fspath.pyimport(ensuresyspath=True) + mod = self.fspath.pyimport(ensuresyspath="append") except SyntaxError: raise self.CollectError( py.code.ExceptionInfo().getrepr(style="short")) @@ -2057,3 +2057,4 @@ def get_scope_node(node, scope): return node.session raise ValueError("unknown scope") return node.getparent(cls) + diff --git a/setup.py b/setup.py index 5af27b1f5..4671132c5 100644 --- a/setup.py +++ b/setup.py @@ -31,12 +31,12 @@ def get_version(): def has_environment_marker_support(): """ Tests that setuptools has support for PEP-426 environment marker support. - - The first known release to support it is 0.7 (and the earliest on PyPI seems to be 0.7.2 + + The first known release to support it is 0.7 (and the earliest on PyPI seems to be 0.7.2 so we're using that), see: http://pythonhosted.org/setuptools/history.html#id142 - + References: - + * https://wheel.readthedocs.org/en/latest/index.html#defining-conditional-dependencies * https://www.python.org/dev/peps/pep-0426/#environment-markers """ @@ -48,7 +48,7 @@ def has_environment_marker_support(): def main(): - install_requires = ['py>=1.4.25'] + install_requires = ['py>=1.4.27.dev2'] extras_require = {} if has_environment_marker_support(): extras_require[':python_version=="2.6" or python_version=="3.0" or python_version=="3.1"'] = ['argparse'] diff --git a/testing/python/collect.py b/testing/python/collect.py index bdea33a7f..c84c4c733 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -1,3 +1,5 @@ +import sys +from textwrap import dedent import pytest, py class TestModule: @@ -23,6 +25,24 @@ class TestModule: "*HINT*", ]) + def test_import_appends_for_import(self, testdir, monkeypatch): + syspath = list(sys.path) + monkeypatch.setattr(sys, "path", syspath) + root1 = testdir.mkdir("root1") + root2 = testdir.mkdir("root2") + root1.ensure("x456.py") + root2.ensure("x456.py") + p = root2.join("test_x456.py") + p.write(dedent("""\ + import x456 + def test(): + assert x456.__file__.startswith(%r) + """ % str(root1))) + syspath.insert(0, str(root1)) + with root2.as_cwd(): + reprec = testdir.inline_run() + reprec.assertoutcome(passed=1) + def test_syntax_error_in_module(self, testdir): modcol = testdir.getmodulecol("this is a syntax error") pytest.raises(modcol.CollectError, modcol.collect) diff --git a/testing/python/integration.py b/testing/python/integration.py index 96cc9dc5b..1b9be5968 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -238,7 +238,7 @@ def test_pytestconfig_is_session_scoped(): class TestNoselikeTestAttribute: - def test_module(self, testdir): + def test_module_with_global_test(self, testdir): testdir.makepyfile(""" __test__ = False def test_hello(): @@ -248,7 +248,7 @@ class TestNoselikeTestAttribute: assert not reprec.getfailedcollections() calls = reprec.getreports("pytest_runtest_logreport") assert not calls - + def test_class_and_method(self, testdir): testdir.makepyfile(""" __test__ = True diff --git a/testing/test_core.py b/testing/test_core.py index 631e88ae9..51c20c871 100644 --- a/testing/test_core.py +++ b/testing/test_core.py @@ -772,6 +772,7 @@ def test_default_markers(testdir): ]) def test_importplugin_issue375(testdir): + testdir.syspathinsert(testdir.tmpdir) testdir.makepyfile(qwe="import aaaa") excinfo = pytest.raises(ImportError, lambda: importplugin("qwe")) assert "qwe" not in str(excinfo.value)