Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor coverage tests #10209

Merged
merged 4 commits into from Jun 30, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
246 changes: 127 additions & 119 deletions src/python/pants/backend/python/rules/coverage_integration_test.py
Expand Up @@ -10,139 +10,139 @@


class CoverageIntegrationTest(PantsRunIntegrationTest):
def test_coverage(self) -> None:
with temporary_dir(root_dir=get_buildroot()) as tmpdir:
tmpdir_relative = Path(tmpdir).relative_to(get_buildroot())
src_root = Path(tmpdir, "src", "python", "project")
src_root.mkdir(parents=True)
(src_root / "__init__.py").touch()

# Set up the source files. Only `lib.py` will actually be tested, but we still expect
# `random.py` to show up in the final report correctly.
(src_root / "lib.py").write_text(
dedent(
"""\
def add(x, y):
return x + y

def subtract(x, y):
return x - y

def multiply(x, y):
return x * y
"""
)
def _prepare_sources(self, tmpdir, build_root):
asherf marked this conversation as resolved.
Show resolved Hide resolved
tmpdir_relative = Path(tmpdir).relative_to(build_root)
src_root = Path(tmpdir, "src", "python", "project")
src_root.mkdir(parents=True)
(src_root / "__init__.py").touch()

# Set up the source files. Only `lib.py` will actually be tested, but we still expect
# `random.py` to show up in the final report correctly.
(src_root / "lib.py").write_text(
dedent(
"""\
def add(x, y):
return x + y

def subtract(x, y):
return x - y

def multiply(x, y):
return x * y
"""
)
(src_root / "random.py").write_text(
dedent(
"""\
def capitalize(s):
return s.capitalize()
"""
)
)
(src_root / "random.py").write_text(
dedent(
"""\
def capitalize(s):
return s.capitalize()
"""
)
)

# Only test half of the library.
(src_root / "lib_test.py").write_text(
dedent(
"""\
from project.lib import add
# Only test half of the library.
(src_root / "lib_test.py").write_text(
dedent(
"""\
from project.lib import add

def test_add():
assert add(2, 3) == 5
"""
)
def test_add():
assert add(2, 3) == 5
"""
)
)

(src_root / "BUILD").write_text(
dedent(
"""\
python_library()
(src_root / "BUILD").write_text(
dedent(
"""\
python_library()

python_tests(
name="tests",
dependencies=[":project"],
)
"""
python_tests(
name="tests",
dependencies=[":project"],
)
"""
)
)

# Test that a `tests/` source root accurately gets coverage data for the `src/` root.
test_root = Path(tmpdir, "tests", "python", "project_test")
test_root.mkdir(parents=True)
(test_root / "__init__.py").touch()
(test_root / "test_multiply.py").write_text(
dedent(
"""\
from project.lib import multiply

def test_multiply():
assert multiply(2, 3) == 6
"""
)
# Test that a `tests/` source root accurately gets coverage data for the `src/` root.
test_root = Path(tmpdir, "tests", "python", "project_test")
test_root.mkdir(parents=True)
(test_root / "__init__.py").touch()
(test_root / "test_multiply.py").write_text(
dedent(
"""\
from project.lib import multiply

def test_multiply():
assert multiply(2, 3) == 6
"""
)
(test_root / "test_arithmetic.py").write_text(
dedent(
"""\
from project.lib import add, subtract

def test_arithmetic():
assert add(4, 3) == 7 == subtract(10, 3)
"""
)
)
(test_root / "test_arithmetic.py").write_text(
dedent(
"""\
from project.lib import add, subtract

def test_arithmetic():
assert add(4, 3) == 7 == subtract(10, 3)
"""
)
(test_root / "BUILD").write_text(
dedent(
f"""\
python_tests(
name="multiply",
sources=["test_multiply.py"],
dependencies=['{tmpdir_relative}/src/python/project'],
)

python_tests(
name="arithmetic",
sources=["test_arithmetic.py"],
dependencies=['{tmpdir_relative}/src/python/project'],
)
"""
)
(test_root / "BUILD").write_text(
dedent(
f"""\
python_tests(
name="multiply",
sources=["test_multiply.py"],
dependencies=['{tmpdir_relative}/src/python/project'],
)
)

# Test a file that does not cover any src code. While this is unlikely to happen, this
# tests that we can properly handle the edge case. In particular, we want to make sure
# that coverage still works when we omit this test file through the option
# `--omit-test-sources`.
no_src_folder = Path(tmpdir, "tests", "python", "project_test", "no_src")
no_src_folder.mkdir()
(no_src_folder / "__init__.py").touch()
(no_src_folder / "test_no_src.py").write_text(
"def test_true():\n\tassert True is True\n"
)
(no_src_folder / "BUILD").write_text("python_tests()")

command = [
"--no-v1",
"--v2",
"test",
"--use-coverage",
f"{tmpdir_relative}/src/python/project:tests",
f"{tmpdir_relative}/tests/python/project_test:multiply",
f"{tmpdir_relative}/tests/python/project_test:arithmetic",
f"{tmpdir_relative}/tests/python/project_test/no_src",
]
default_result = self.run_pants(command)
filter_result = self.run_pants(
[*command, "--coverage-py-filter=['project.lib', 'project_test.no_src']"]
python_tests(
name="arithmetic",
sources=["test_arithmetic.py"],
dependencies=['{tmpdir_relative}/src/python/project'],
)
"""
)
)
# Test a file that does not cover any src code. While this is unlikely to happen, this
# tests that we can properly handle the edge case. In particular, we want to make sure
# that coverage still works when we omit this test file through the option
# `--omit-test-sources`.
no_src_folder = Path(tmpdir, "tests", "python", "project_test", "no_src")
no_src_folder.mkdir()
(no_src_folder / "__init__.py").touch()
(no_src_folder / "test_no_src.py").write_text("def test_true():\n\tassert True is True\n")
(no_src_folder / "BUILD").write_text("python_tests()")
return tmpdir_relative

def _run_tests(self, tmpdir_relative, *more_args: str):
asherf marked this conversation as resolved.
Show resolved Hide resolved
command = [
"--no-v1",
"--v2",
"test",
"--use-coverage",
f"{tmpdir_relative}/src/python/project:tests",
f"{tmpdir_relative}/tests/python/project_test:multiply",
f"{tmpdir_relative}/tests/python/project_test:arithmetic",
f"{tmpdir_relative}/tests/python/project_test/no_src",
]
command.extend(more_args)
result = self.run_pants(command)
assert result.returncode == 0
# Regression test: make sure that individual tests do not complain about failing to
# generate reports. This was showing up at test-time, even though the final merged
# report would work properly.
assert "Failed to generate report" not in result.stderr_data
return result

for result in (default_result, filter_result):
assert result.returncode == 0
# Regression test: make sure that individual tests do not complain about failing to
# generate reports. This was showing up at test-time, even though the final merged
# report would work properly.
assert "Failed to generate report" not in result.stderr_data

def test_coverage(self) -> None:
build_root = get_buildroot()
with temporary_dir(root_dir=build_root) as tmpdir:
tmpdir_relative = self._prepare_sources(tmpdir, build_root)
result = self._run_tests(tmpdir_relative)
assert (
dedent(
f"""\
Expand All @@ -159,8 +159,16 @@ def test_arithmetic():
TOTAL 19 2 0 0 89%
"""
)
in default_result.stderr_data
in result.stderr_data
)

def test_coverage_with_filter(self) -> None:
build_root = get_buildroot()
with temporary_dir(root_dir=build_root) as tmpdir:
tmpdir_relative = self._prepare_sources(tmpdir, build_root)
result = self._run_tests(
tmpdir_relative, "--coverage-py-filter=['project.lib', 'project_test.no_src']"
)
assert (
dedent(
f"""\
Expand All @@ -172,5 +180,5 @@ def test_arithmetic():
TOTAL 8 0 0 0 100%
"""
)
in filter_result.stderr_data
in result.stderr_data
)