summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2021-10-31 07:41:48 -0400
committerNed Batchelder <ned@nedbatchelder.com>2021-10-31 09:17:11 -0400
commit7589066bfe18bd6f26200895cc2e569128fafead (patch)
tree6efcb51eea6ea69af38c6008ec97829b8ed89622
parent3b7f8c1dd7aceea22f35224729b36d19c1dbdcbd (diff)
downloadpython-coveragepy-git-7589066bfe18bd6f26200895cc2e569128fafead.tar.gz
refactor(test): the virtualenv tests deserve their own file
-rw-r--r--tests/test_process.py264
-rw-r--r--tests/test_venv.py276
2 files changed, 277 insertions, 263 deletions
diff --git a/tests/test_process.py b/tests/test_process.py
index 1b17160f..7d7875d0 100644
--- a/tests/test_process.py
+++ b/tests/test_process.py
@@ -7,7 +7,6 @@ import glob
import os
import os.path
import re
-import shutil
import stat
import sys
import sysconfig
@@ -23,8 +22,7 @@ from coverage.data import line_counts
from coverage.files import abs_file, python_reported_file
from tests.coveragetest import CoverageTest, TESTS_DIR
-from tests.helpers import change_dir, make_file, nice_file, os_sep
-from tests.helpers import re_lines, re_lines_text, run_command
+from tests.helpers import os_sep, re_lines_text
class ProcessTest(CoverageTest):
@@ -1662,263 +1660,3 @@ class ProcessStartupWithSourceTest(ProcessCoverageMixin, CoverageTest):
def test_script_pkg_sub(self):
self.assert_pth_and_source_work_together('', 'pkg', 'sub')
-
-
-def run_in_venv(cmd):
- r"""Run `cmd` in the virtualenv at `venv`.
-
- The first word of the command will be adjusted to run it from the
- venv/bin or venv\Scripts directory.
-
- Returns the text output of the command.
- """
- words = cmd.split()
- if env.WINDOWS:
- words[0] = fr"venv\Scripts\{words[0]}.exe"
- else:
- words[0] = fr"venv/bin/{words[0]}"
- status, output = run_command(" ".join(words))
- assert status == 0
- return output
-
-
-@pytest.fixture(scope="session", name="venv_world")
-def venv_world_fixture(tmp_path_factory):
- """Create a virtualenv with a few test packages for VirtualenvTest to use.
-
- Returns the directory containing the "venv" virtualenv.
- """
-
- venv_world = tmp_path_factory.mktemp("venv_world")
- with change_dir(venv_world):
- # Create a virtualenv.
- run_command("python -m venv venv")
-
- # A third-party package that installs a few different packages.
- make_file("third_pkg/third/__init__.py", """\
- import fourth
- def third(x):
- return 3 * x
- """)
- # Use plugin2.py as third.plugin
- with open(os.path.join(os.path.dirname(__file__), "plugin2.py")) as f:
- make_file("third_pkg/third/plugin.py", f.read())
- # A render function for plugin2 to use for dynamic file names.
- make_file("third_pkg/third/render.py", """\
- def render(filename, linenum):
- return "HTML: {}@{}".format(filename, linenum)
- """)
- # Another package that third can use.
- make_file("third_pkg/fourth/__init__.py", """\
- def fourth(x):
- return 4 * x
- """)
- # Some namespace packages.
- make_file("third_pkg/nspkg/fifth/__init__.py", """\
- def fifth(x):
- return 5 * x
- """)
- # The setup.py to install everything.
- make_file("third_pkg/setup.py", """\
- import setuptools
- setuptools.setup(
- name="third",
- packages=["third", "fourth", "nspkg.fifth"],
- )
- """)
-
- # Some namespace packages.
- make_file("another_pkg/nspkg/sixth/__init__.py", """\
- def sixth(x):
- return 6 * x
- """)
- # The setup.py to install everything.
- make_file("another_pkg/setup.py", """\
- import setuptools
- setuptools.setup(
- name="another",
- packages=["nspkg.sixth"],
- )
- """)
-
- # Install the third-party packages.
- run_in_venv("python -m pip install --no-index ./third_pkg")
- run_in_venv("python -m pip install --no-index -e ./another_pkg")
- shutil.rmtree("third_pkg")
-
- # Install coverage.
- coverage_src = nice_file(TESTS_DIR, "..")
- run_in_venv(f"python -m pip install --no-index {coverage_src}")
-
- return venv_world
-
-
-@pytest.fixture(params=[
- "coverage",
- "python -m coverage",
-], name="coverage_command")
-def coverage_command_fixture(request):
- """Parametrized fixture to use multiple forms of "coverage" command."""
- return request.param
-
-
-class VirtualenvTest(CoverageTest):
- """Tests of virtualenv considerations."""
-
- expected_stdout = "33\n110\n198\n1.5\n"
-
- @pytest.fixture(autouse=True)
- def in_venv_world_fixture(self, venv_world):
- """For running tests inside venv_world, and cleaning up made files."""
- with change_dir(venv_world):
- self.make_file("myproduct.py", """\
- import colorsys
- import third
- import nspkg.fifth
- import nspkg.sixth
- print(third.third(11))
- print(nspkg.fifth.fifth(22))
- print(nspkg.sixth.sixth(33))
- print(sum(colorsys.rgb_to_hls(1, 0, 0)))
- """)
-
- self.del_environ("COVERAGE_TESTING") # To avoid needing contracts installed.
- self.set_environ("COVERAGE_DEBUG_FILE", "debug_out.txt")
- self.set_environ("COVERAGE_DEBUG", "trace")
-
- yield
-
- for fname in os.listdir("."):
- if fname not in {"venv", "another_pkg"}:
- os.remove(fname)
-
- def get_trace_output(self):
- """Get the debug output of coverage.py"""
- with open("debug_out.txt") as f:
- return f.read()
-
- def test_third_party_venv_isnt_measured(self, coverage_command):
- out = run_in_venv(coverage_command + " run --source=. myproduct.py")
- # In particular, this warning doesn't appear:
- # Already imported a file that will be measured: .../coverage/__main__.py
- assert out == self.expected_stdout
-
- # Check that our tracing was accurate. Files are mentioned because
- # --source refers to a file.
- debug_out = self.get_trace_output()
- assert re_lines(
- r"^Not tracing .*\bexecfile.py': inside --source, but is third-party",
- debug_out,
- )
- assert re_lines(r"^Tracing .*\bmyproduct.py", debug_out)
- assert re_lines(
- r"^Not tracing .*\bcolorsys.py': falls outside the --source spec",
- debug_out,
- )
-
- out = run_in_venv("python -m coverage report")
- assert "myproduct.py" in out
- assert "third" not in out
- assert "coverage" not in out
- assert "colorsys" not in out
-
- def test_us_in_venv_isnt_measured(self, coverage_command):
- out = run_in_venv(coverage_command + " run --source=third myproduct.py")
- assert out == self.expected_stdout
-
- # Check that our tracing was accurate. Modules are mentioned because
- # --source refers to a module.
- debug_out = self.get_trace_output()
- assert re_lines(
- r"^Not tracing .*\bexecfile.py': " +
- "module 'coverage.execfile' falls outside the --source spec",
- debug_out,
- )
- assert re_lines(
- r"^Not tracing .*\bmyproduct.py': module 'myproduct' falls outside the --source spec",
- debug_out,
- )
- assert re_lines(
- r"^Not tracing .*\bcolorsys.py': module 'colorsys' falls outside the --source spec",
- debug_out,
- )
-
- out = run_in_venv("python -m coverage report")
- assert "myproduct.py" not in out
- assert "third" in out
- assert "coverage" not in out
- assert "colorsys" not in out
-
- def test_venv_isnt_measured(self, coverage_command):
- out = run_in_venv(coverage_command + " run myproduct.py")
- assert out == self.expected_stdout
-
- debug_out = self.get_trace_output()
- assert re_lines(r"^Not tracing .*\bexecfile.py': is part of coverage.py", debug_out)
- assert re_lines(r"^Tracing .*\bmyproduct.py", debug_out)
- assert re_lines(r"^Not tracing .*\bcolorsys.py': is in the stdlib", debug_out)
-
- out = run_in_venv("python -m coverage report")
- assert "myproduct.py" in out
- assert "third" not in out
- assert "coverage" not in out
- assert "colorsys" not in out
-
- @pytest.mark.skipif(not env.C_TRACER, reason="Plugins are only supported with the C tracer.")
- def test_venv_with_dynamic_plugin(self, coverage_command):
- # https://github.com/nedbat/coveragepy/issues/1150
- # Django coverage plugin was incorrectly getting warnings:
- # "Already imported: ... django/template/blah.py"
- # It happened because coverage imported the plugin, which imported
- # Django, and then the Django files were reported as traceable.
- self.make_file(".coveragerc", "[run]\nplugins=third.plugin\n")
- self.make_file("myrender.py", """\
- import third.render
- print(third.render.render("hello.html", 1723))
- """)
- out = run_in_venv(coverage_command + " run --source=. myrender.py")
- # The output should not have this warning:
- # Already imported a file that will be measured: ...third/render.py (already-imported)
- assert out == "HTML: hello.html@1723\n"
-
- def test_installed_namespace_packages(self, coverage_command):
- # https://github.com/nedbat/coveragepy/issues/1231
- # When namespace packages were installed, they were considered
- # third-party packages. Test that isn't still happening.
- out = run_in_venv(coverage_command + " run --source=nspkg myproduct.py")
- # In particular, this warning doesn't appear:
- # Already imported a file that will be measured: .../coverage/__main__.py
- assert out == self.expected_stdout
-
- # Check that our tracing was accurate. Files are mentioned because
- # --source refers to a file.
- debug_out = self.get_trace_output()
- assert re_lines(
- r"^Not tracing .*\bexecfile.py': " +
- "module 'coverage.execfile' falls outside the --source spec",
- debug_out,
- )
- assert re_lines(
- r"^Not tracing .*\bmyproduct.py': module 'myproduct' falls outside the --source spec",
- debug_out,
- )
- assert re_lines(
- r"^Not tracing .*\bcolorsys.py': module 'colorsys' falls outside the --source spec",
- debug_out,
- )
-
- out = run_in_venv("python -m coverage report")
-
- # Name Stmts Miss Cover
- # ------------------------------------------------------------------------------
- # another_pkg/nspkg/sixth/__init__.py 2 0 100%
- # venv/lib/python3.9/site-packages/nspkg/fifth/__init__.py 2 0 100%
- # ------------------------------------------------------------------------------
- # TOTAL 4 0 100%
-
- assert "myproduct.py" not in out
- assert "third" not in out
- assert "coverage" not in out
- assert "colorsys" not in out
- assert "fifth" in out
- assert "sixth" in out
diff --git a/tests/test_venv.py b/tests/test_venv.py
new file mode 100644
index 00000000..e6610337
--- /dev/null
+++ b/tests/test_venv.py
@@ -0,0 +1,276 @@
+# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
+# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
+
+"""Tests about understanding how third-party code is installed."""
+
+import os
+import os.path
+import shutil
+
+import pytest
+
+from coverage import env
+
+from tests.coveragetest import CoverageTest, TESTS_DIR
+from tests.helpers import change_dir, make_file, nice_file
+from tests.helpers import re_lines, run_command
+
+
+def run_in_venv(cmd):
+ r"""Run `cmd` in the virtualenv at `venv`.
+
+ The first word of the command will be adjusted to run it from the
+ venv/bin or venv\Scripts directory.
+
+ Returns the text output of the command.
+ """
+ words = cmd.split()
+ if env.WINDOWS:
+ words[0] = fr"venv\Scripts\{words[0]}.exe"
+ else:
+ words[0] = fr"venv/bin/{words[0]}"
+ status, output = run_command(" ".join(words))
+ assert status == 0
+ return output
+
+
+@pytest.fixture(scope="session", name="venv_world")
+def venv_world_fixture(tmp_path_factory):
+ """Create a virtualenv with a few test packages for VirtualenvTest to use.
+
+ Returns the directory containing the "venv" virtualenv.
+ """
+
+ venv_world = tmp_path_factory.mktemp("venv_world")
+ with change_dir(venv_world):
+ # Create a virtualenv.
+ run_command("python -m venv venv")
+
+ # A third-party package that installs a few different packages.
+ make_file("third_pkg/third/__init__.py", """\
+ import fourth
+ def third(x):
+ return 3 * x
+ """)
+ # Use plugin2.py as third.plugin
+ with open(os.path.join(os.path.dirname(__file__), "plugin2.py")) as f:
+ make_file("third_pkg/third/plugin.py", f.read())
+ # A render function for plugin2 to use for dynamic file names.
+ make_file("third_pkg/third/render.py", """\
+ def render(filename, linenum):
+ return "HTML: {}@{}".format(filename, linenum)
+ """)
+ # Another package that third can use.
+ make_file("third_pkg/fourth/__init__.py", """\
+ def fourth(x):
+ return 4 * x
+ """)
+ # Some namespace packages.
+ make_file("third_pkg/nspkg/fifth/__init__.py", """\
+ def fifth(x):
+ return 5 * x
+ """)
+ # The setup.py to install everything.
+ make_file("third_pkg/setup.py", """\
+ import setuptools
+ setuptools.setup(
+ name="third",
+ packages=["third", "fourth", "nspkg.fifth"],
+ )
+ """)
+
+ # Some namespace packages.
+ make_file("another_pkg/nspkg/sixth/__init__.py", """\
+ def sixth(x):
+ return 6 * x
+ """)
+ # The setup.py to install everything.
+ make_file("another_pkg/setup.py", """\
+ import setuptools
+ setuptools.setup(
+ name="another",
+ packages=["nspkg.sixth"],
+ )
+ """)
+
+ # Install the third-party packages.
+ run_in_venv("python -m pip install --no-index ./third_pkg")
+ run_in_venv("python -m pip install --no-index -e ./another_pkg")
+ shutil.rmtree("third_pkg")
+
+ # Install coverage.
+ coverage_src = nice_file(TESTS_DIR, "..")
+ run_in_venv(f"python -m pip install --no-index {coverage_src}")
+
+ return venv_world
+
+
+@pytest.fixture(params=[
+ "coverage",
+ "python -m coverage",
+], name="coverage_command")
+def coverage_command_fixture(request):
+ """Parametrized fixture to use multiple forms of "coverage" command."""
+ return request.param
+
+
+class VirtualenvTest(CoverageTest):
+ """Tests of virtualenv considerations."""
+
+ expected_stdout = "33\n110\n198\n1.5\n"
+
+ @pytest.fixture(autouse=True)
+ def in_venv_world_fixture(self, venv_world):
+ """For running tests inside venv_world, and cleaning up made files."""
+ with change_dir(venv_world):
+ self.make_file("myproduct.py", """\
+ import colorsys
+ import third
+ import nspkg.fifth
+ import nspkg.sixth
+ print(third.third(11))
+ print(nspkg.fifth.fifth(22))
+ print(nspkg.sixth.sixth(33))
+ print(sum(colorsys.rgb_to_hls(1, 0, 0)))
+ """)
+
+ self.del_environ("COVERAGE_TESTING") # To avoid needing contracts installed.
+ self.set_environ("COVERAGE_DEBUG_FILE", "debug_out.txt")
+ self.set_environ("COVERAGE_DEBUG", "trace")
+
+ yield
+
+ for fname in os.listdir("."):
+ if fname not in {"venv", "another_pkg"}:
+ os.remove(fname)
+
+ def get_trace_output(self):
+ """Get the debug output of coverage.py"""
+ with open("debug_out.txt") as f:
+ return f.read()
+
+ def test_third_party_venv_isnt_measured(self, coverage_command):
+ out = run_in_venv(coverage_command + " run --source=. myproduct.py")
+ # In particular, this warning doesn't appear:
+ # Already imported a file that will be measured: .../coverage/__main__.py
+ assert out == self.expected_stdout
+
+ # Check that our tracing was accurate. Files are mentioned because
+ # --source refers to a file.
+ debug_out = self.get_trace_output()
+ assert re_lines(
+ r"^Not tracing .*\bexecfile.py': inside --source, but is third-party",
+ debug_out,
+ )
+ assert re_lines(r"^Tracing .*\bmyproduct.py", debug_out)
+ assert re_lines(
+ r"^Not tracing .*\bcolorsys.py': falls outside the --source spec",
+ debug_out,
+ )
+
+ out = run_in_venv("python -m coverage report")
+ assert "myproduct.py" in out
+ assert "third" not in out
+ assert "coverage" not in out
+ assert "colorsys" not in out
+
+ def test_us_in_venv_isnt_measured(self, coverage_command):
+ out = run_in_venv(coverage_command + " run --source=third myproduct.py")
+ assert out == self.expected_stdout
+
+ # Check that our tracing was accurate. Modules are mentioned because
+ # --source refers to a module.
+ debug_out = self.get_trace_output()
+ assert re_lines(
+ r"^Not tracing .*\bexecfile.py': " +
+ "module 'coverage.execfile' falls outside the --source spec",
+ debug_out,
+ )
+ assert re_lines(
+ r"^Not tracing .*\bmyproduct.py': module 'myproduct' falls outside the --source spec",
+ debug_out,
+ )
+ assert re_lines(
+ r"^Not tracing .*\bcolorsys.py': module 'colorsys' falls outside the --source spec",
+ debug_out,
+ )
+
+ out = run_in_venv("python -m coverage report")
+ assert "myproduct.py" not in out
+ assert "third" in out
+ assert "coverage" not in out
+ assert "colorsys" not in out
+
+ def test_venv_isnt_measured(self, coverage_command):
+ out = run_in_venv(coverage_command + " run myproduct.py")
+ assert out == self.expected_stdout
+
+ debug_out = self.get_trace_output()
+ assert re_lines(r"^Not tracing .*\bexecfile.py': is part of coverage.py", debug_out)
+ assert re_lines(r"^Tracing .*\bmyproduct.py", debug_out)
+ assert re_lines(r"^Not tracing .*\bcolorsys.py': is in the stdlib", debug_out)
+
+ out = run_in_venv("python -m coverage report")
+ assert "myproduct.py" in out
+ assert "third" not in out
+ assert "coverage" not in out
+ assert "colorsys" not in out
+
+ @pytest.mark.skipif(not env.C_TRACER, reason="Plugins are only supported with the C tracer.")
+ def test_venv_with_dynamic_plugin(self, coverage_command):
+ # https://github.com/nedbat/coveragepy/issues/1150
+ # Django coverage plugin was incorrectly getting warnings:
+ # "Already imported: ... django/template/blah.py"
+ # It happened because coverage imported the plugin, which imported
+ # Django, and then the Django files were reported as traceable.
+ self.make_file(".coveragerc", "[run]\nplugins=third.plugin\n")
+ self.make_file("myrender.py", """\
+ import third.render
+ print(third.render.render("hello.html", 1723))
+ """)
+ out = run_in_venv(coverage_command + " run --source=. myrender.py")
+ # The output should not have this warning:
+ # Already imported a file that will be measured: ...third/render.py (already-imported)
+ assert out == "HTML: hello.html@1723\n"
+
+ def test_installed_namespace_packages(self, coverage_command):
+ # https://github.com/nedbat/coveragepy/issues/1231
+ # When namespace packages were installed, they were considered
+ # third-party packages. Test that isn't still happening.
+ out = run_in_venv(coverage_command + " run --source=nspkg myproduct.py")
+ # In particular, this warning doesn't appear:
+ # Already imported a file that will be measured: .../coverage/__main__.py
+ assert out == self.expected_stdout
+
+ # Check that our tracing was accurate. Files are mentioned because
+ # --source refers to a file.
+ debug_out = self.get_trace_output()
+ assert re_lines(
+ r"^Not tracing .*\bexecfile.py': " +
+ "module 'coverage.execfile' falls outside the --source spec",
+ debug_out,
+ )
+ assert re_lines(
+ r"^Not tracing .*\bmyproduct.py': module 'myproduct' falls outside the --source spec",
+ debug_out,
+ )
+ assert re_lines(
+ r"^Not tracing .*\bcolorsys.py': module 'colorsys' falls outside the --source spec",
+ debug_out,
+ )
+
+ out = run_in_venv("python -m coverage report")
+
+ # Name Stmts Miss Cover
+ # ------------------------------------------------------------------------------
+ # another_pkg/nspkg/sixth/__init__.py 2 0 100%
+ # venv/lib/python3.9/site-packages/nspkg/fifth/__init__.py 2 0 100%
+ # ------------------------------------------------------------------------------
+ # TOTAL 4 0 100%
+
+ assert "myproduct.py" not in out
+ assert "third" not in out
+ assert "coverage" not in out
+ assert "colorsys" not in out
+ assert "fifth" in out
+ assert "sixth" in out