summaryrefslogtreecommitdiff
path: root/tests/test_process.py
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2021-04-04 19:31:12 -0400
committerNed Batchelder <ned@nedbatchelder.com>2021-04-10 14:15:45 -0400
commitb3e87bbd648d76b89cccca089b09f82a1f4063f6 (patch)
tree3d7cd073046e003b7e404eeefff004d2eac3655b /tests/test_process.py
parentdc48d27937d4eb0ec5072b97dce54e7556618f8e (diff)
downloadpython-coveragepy-git-nedbat/virtualenv-detection-905.tar.gz
fix: be intelligent about third-party packagesnedbat/virtualenv-detection-905
Avoid measuring code located where third-party packages get installed. We have to take care to measure --source code even if it is installed in a third-party location. This also fixes #905, coverage generating warnings about coverage being imported when it will be measured. https://github.com/nedbat/coveragepy/issues/876 https://github.com/nedbat/coveragepy/issues/905
Diffstat (limited to 'tests/test_process.py')
-rw-r--r--tests/test_process.py100
1 files changed, 99 insertions, 1 deletions
diff --git a/tests/test_process.py b/tests/test_process.py
index 73c4713a..b310b770 100644
--- a/tests/test_process.py
+++ b/tests/test_process.py
@@ -8,6 +8,7 @@ import glob
import os
import os.path
import re
+import shutil
import stat
import sys
import sysconfig
@@ -24,7 +25,7 @@ from coverage.files import abs_file, python_reported_file
from coverage.misc import output_encoding
from tests.coveragetest import CoverageTest, TESTS_DIR
-from tests.helpers import re_lines
+from tests.helpers import change_dir, make_file, nice_file, re_lines, run_command
class ProcessTest(CoverageTest):
@@ -1640,3 +1641,100 @@ class ProcessStartupWithSourceTest(ProcessCoverageMixin, CoverageTest):
def test_script_pkg_sub(self):
self.assert_pth_and_source_work_together('', 'pkg', 'sub')
+
+
+def run_in_venv(args):
+ """Run python with `args` in the "venv" virtualenv.
+
+ Returns the text output of the command.
+ """
+ if env.WINDOWS:
+ cmd = r".\venv\Scripts\python.exe "
+ else:
+ cmd = "./venv/bin/python "
+ cmd += args
+ status, output = run_command(cmd)
+ print(output)
+ assert status == 0
+ return output
+
+
+@pytest.fixture(scope="session", name="venv_factory")
+def venv_factory_fixture(tmp_path_factory):
+ """Produce a function which can copy a venv template to a new directory.
+
+ The function accepts one argument, the directory to use for the venv.
+ """
+ tmpdir = tmp_path_factory.mktemp("venv_template")
+ with change_dir(str(tmpdir)):
+ # Create a virtualenv.
+ run_command("python -m virtualenv venv")
+
+ # A third-party package that installs two different packages.
+ make_file("third_pkg/third/__init__.py", """\
+ import fourth
+ def third(x):
+ return 3 * x
+ """)
+ make_file("third_pkg/fourth/__init__.py", """\
+ def fourth(x):
+ return 4 * x
+ """)
+ make_file("third_pkg/setup.py", """\
+ import setuptools
+ setuptools.setup(name="third", packages=["third", "fourth"])
+ """)
+
+ # Install the third-party packages.
+ run_in_venv("-m pip install --no-index ./third_pkg")
+
+ # Install coverage.
+ coverage_src = nice_file(TESTS_DIR, "..")
+ run_in_venv("-m pip install --no-index {}".format(coverage_src))
+
+ def factory(dst):
+ """The venv factory function.
+
+ Copies the venv template to `dst`.
+ """
+ shutil.copytree(str(tmpdir / "venv"), dst, symlinks=(not env.WINDOWS))
+
+ return factory
+
+
+class VirtualenvTest(CoverageTest):
+ """Tests of virtualenv considerations."""
+
+ def setup_test(self):
+ self.make_file("myproduct.py", """\
+ import third
+ print(third.third(11))
+ """)
+ self.del_environ("COVERAGE_TESTING") # To avoid needing contracts installed.
+ super(VirtualenvTest, self).setup_test()
+
+ def test_third_party_venv_isnt_measured(self, venv_factory):
+ venv_factory("venv")
+ out = run_in_venv("-m coverage run --source=. myproduct.py")
+ # In particular, this warning doesn't appear:
+ # Already imported a file that will be measured: .../coverage/__main__.py
+ assert out == "33\n"
+ out = run_in_venv("-m coverage report")
+ assert "myproduct.py" in out
+ assert "third" not in out
+
+ def test_us_in_venv_is_measured(self, venv_factory):
+ venv_factory("venv")
+ out = run_in_venv("-m coverage run --source=third myproduct.py")
+ assert out == "33\n"
+ out = run_in_venv("-m coverage report")
+ assert "myproduct.py" not in out
+ assert "third" in out
+
+ def test_venv_isnt_measured(self, venv_factory):
+ venv_factory("venv")
+ out = run_in_venv("-m coverage run myproduct.py")
+ assert out == "33\n"
+ out = run_in_venv("-m coverage report")
+ assert "myproduct.py" in out
+ assert "third" not in out