diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2021-04-04 19:31:12 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2021-04-10 14:15:45 -0400 |
commit | b3e87bbd648d76b89cccca089b09f82a1f4063f6 (patch) | |
tree | 3d7cd073046e003b7e404eeefff004d2eac3655b /tests | |
parent | dc48d27937d4eb0ec5072b97dce54e7556618f8e (diff) | |
download | python-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')
-rw-r--r-- | tests/test_debug.py | 5 | ||||
-rw-r--r-- | tests/test_process.py | 100 |
2 files changed, 102 insertions, 3 deletions
diff --git a/tests/test_debug.py b/tests/test_debug.py index 55001c96..cb83e519 100644 --- a/tests/test_debug.py +++ b/tests/test_debug.py @@ -183,8 +183,9 @@ class DebugTraceTest(CoverageTest): out_lines = self.f1_debug_output(["sys"]) labels = """ - version coverage cover_paths pylib_paths tracer configs_attempted config_file - configs_read data_file python platform implementation executable + version coverage coverage_paths stdlib_paths third_party_paths + tracer configs_attempted config_file configs_read data_file + python platform implementation executable pid cwd path environment command_line cover_match pylib_match """.split() for label in labels: 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 |