diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_cmdline.py | 10 | ||||
-rw-r--r-- | tests/test_debug.py | 50 | ||||
-rw-r--r-- | tests/test_execfile.py | 56 | ||||
-rw-r--r-- | tests/test_filereporter.py | 12 | ||||
-rw-r--r-- | tests/test_files.py | 121 | ||||
-rw-r--r-- | tests/test_summary.py | 4 |
6 files changed, 139 insertions, 114 deletions
diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py index 96bd3bbf..f20cfe74 100644 --- a/tests/test_cmdline.py +++ b/tests/test_cmdline.py @@ -20,7 +20,7 @@ from coverage import env from coverage.control import DEFAULT_DATAFILE from coverage.config import CoverageConfig from coverage.exceptions import _ExceptionDuringRun -from coverage.types import TConfigValue +from coverage.types import TConfigValueIn, TConfigValueOut from coverage.version import __url__ from tests.coveragetest import CoverageTest, OK, ERR, command_line @@ -96,7 +96,7 @@ class BaseCmdLineTest(CoverageTest): def mock_command_line( self, args: str, - options: Optional[Mapping[str, TConfigValue]]=None, + options: Optional[Mapping[str, TConfigValueIn]]=None, ) -> Tuple[mock.Mock, int]: """Run `args` through the command line, with a Mock. @@ -130,7 +130,7 @@ class BaseCmdLineTest(CoverageTest): args: str, code: str, ret: int=OK, - options: Optional[Mapping[str, TConfigValue]]=None, + options: Optional[Mapping[str, TConfigValueIn]]=None, ) -> None: """Assert that the `args` end up executing the sequence in `code`.""" called, status = self.mock_command_line(args, options=options) @@ -1139,10 +1139,10 @@ class CoverageReportingFake: self.json_result = json_report self.lcov_result = lcov_result - def set_option(self, optname: str, optvalue: TConfigValue) -> None: + def set_option(self, optname: str, optvalue: TConfigValueIn) -> None: self.config.set_option(optname, optvalue) - def get_option(self, optname: str) -> TConfigValue: + def get_option(self, optname: str) -> TConfigValueOut: return self.config.get_option(optname) def load(self) -> None: diff --git a/tests/test_debug.py b/tests/test_debug.py index b4ce6d92..73217f1a 100644 --- a/tests/test_debug.py +++ b/tests/test_debug.py @@ -9,6 +9,8 @@ import os import re import sys +from typing import Any, Callable, Iterable + import pytest import coverage @@ -25,7 +27,7 @@ class InfoFormatterTest(CoverageTest): run_in_temp_dir = False - def test_info_formatter(self): + def test_info_formatter(self) -> None: lines = list(info_formatter([ ('x', 'hello there'), ('very long label', ['one element']), @@ -43,7 +45,7 @@ class InfoFormatterTest(CoverageTest): ] assert expected == lines - def test_info_formatter_with_generator(self): + def test_info_formatter_with_generator(self) -> None: lines = list(info_formatter(('info%d' % i, i) for i in range(3))) expected = [ ' info0: 0', @@ -52,7 +54,7 @@ class InfoFormatterTest(CoverageTest): ] assert expected == lines - def test_too_long_label(self): + def test_too_long_label(self) -> None: with pytest.raises(AssertionError): list(info_formatter([('this label is way too long and will not fit', 23)])) @@ -61,7 +63,7 @@ class InfoFormatterTest(CoverageTest): ("x", "-- x ---------------------------------------------------------"), ("hello there", "-- hello there -----------------------------------------------"), ]) -def test_info_header(label, header): +def test_info_header(label: str, header: str) -> None: assert info_header(label) == header @@ -71,7 +73,7 @@ def test_info_header(label, header): (0xA5A55A5A, 0xFFFF), (0x1234cba956780fed, 0x8008), ]) -def test_short_id(id64, id16): +def test_short_id(id64: int, id16: int) -> None: assert short_id(id64) == id16 @@ -79,7 +81,7 @@ def test_short_id(id64, id16): ("hello", 10, "'hello'"), ("0123456789abcdefghijklmnopqrstuvwxyz", 15, "'01234...vwxyz'"), ]) -def test_clipped_repr(text, numchars, result): +def test_clipped_repr(text: str, numchars: int, result: str) -> None: assert clipped_repr(text, numchars) == result @@ -90,14 +92,18 @@ def test_clipped_repr(text, numchars, result): ("hello\nbye\n", [lambda x: "="+x], "=hello\n=bye\n"), ("hello\nbye\n", [lambda x: "="+x, lambda x: x+"\ndone\n"], "=hello\ndone\n=bye\ndone\n"), ]) -def test_filter_text(text, filters, result): +def test_filter_text( + text: str, + filters: Iterable[Callable[[str], str]], + result: str, +) -> None: assert filter_text(text, filters) == result class DebugTraceTest(CoverageTest): """Tests of debug output.""" - def f1_debug_output(self, debug): + def f1_debug_output(self, debug: Iterable[str]) -> str: """Runs some code with `debug` option, returns the debug output.""" # Make code to run. self.make_file("f1.py", """\ @@ -116,13 +122,13 @@ class DebugTraceTest(CoverageTest): return debug_out.getvalue() - def test_debug_no_trace(self): + def test_debug_no_trace(self) -> None: out_text = self.f1_debug_output([]) # We should have no output at all. assert not out_text - def test_debug_trace(self): + def test_debug_trace(self) -> None: out_text = self.f1_debug_output(["trace"]) # We should have a line like "Tracing 'f1.py'", perhaps with an @@ -132,7 +138,7 @@ class DebugTraceTest(CoverageTest): # We should have lines like "Not tracing 'collector.py'..." assert re_lines(r"^Not tracing .*: is part of coverage.py$", out_text) - def test_debug_trace_pid(self): + def test_debug_trace_pid(self) -> None: out_text = self.f1_debug_output(["trace", "pid"]) # Now our lines are always prefixed with the process id. @@ -144,7 +150,7 @@ class DebugTraceTest(CoverageTest): assert re_lines(pid_prefix + "Tracing ", out_text) assert re_lines(pid_prefix + "Not tracing ", out_text) - def test_debug_callers(self): + def test_debug_callers(self) -> None: out_text = self.f1_debug_output(["pid", "dataop", "dataio", "callers", "lock"]) # For every real message, there should be a stack trace with a line like # "f1_debug_output : /Users/ned/coverage/tests/test_debug.py @71" @@ -161,7 +167,7 @@ class DebugTraceTest(CoverageTest): assert re_lines(r"^\s*\d+\.\w{4}: Adding file tracers: 0 files", real_messages[-1]) assert re_lines(r"\s+add_file_tracers : .*coverage[/\\]sqldata.py:\d+$", last_line) - def test_debug_config(self): + def test_debug_config(self) -> None: out_text = self.f1_debug_output(["config"]) labels = """ @@ -176,7 +182,7 @@ class DebugTraceTest(CoverageTest): msg = f"Incorrect lines for {label!r}" assert 1 == len(re_lines(label_pat, out_text)), msg - def test_debug_sys(self): + def test_debug_sys(self) -> None: out_text = self.f1_debug_output(["sys"]) labels = """ @@ -190,7 +196,7 @@ class DebugTraceTest(CoverageTest): msg = f"Incorrect lines for {label!r}" assert 1 == len(re_lines(label_pat, out_text)), msg - def test_debug_sys_ctracer(self): + def test_debug_sys_ctracer(self) -> None: out_text = self.f1_debug_output(["sys"]) tracer_line = re_line(r"CTracer:", out_text).strip() if env.C_TRACER: @@ -199,7 +205,7 @@ class DebugTraceTest(CoverageTest): expected = "CTracer: unavailable" assert expected == tracer_line - def test_debug_pybehave(self): + def test_debug_pybehave(self) -> None: out_text = self.f1_debug_output(["pybehave"]) out_lines = out_text.splitlines() assert 10 < len(out_lines) < 40 @@ -208,15 +214,15 @@ class DebugTraceTest(CoverageTest): assert vtuple[:5] == sys.version_info -def f_one(*args, **kwargs): +def f_one(*args: Any, **kwargs: Any) -> str: """First of the chain of functions for testing `short_stack`.""" return f_two(*args, **kwargs) -def f_two(*args, **kwargs): +def f_two(*args: Any, **kwargs: Any) -> str: """Second of the chain of functions for testing `short_stack`.""" return f_three(*args, **kwargs) -def f_three(*args, **kwargs): +def f_three(*args: Any, **kwargs: Any) -> str: """Third of the chain of functions for testing `short_stack`.""" return short_stack(*args, **kwargs) @@ -226,17 +232,17 @@ class ShortStackTest(CoverageTest): run_in_temp_dir = False - def test_short_stack(self): + def test_short_stack(self) -> None: stack = f_one().splitlines() assert len(stack) > 10 assert "f_three" in stack[-1] assert "f_two" in stack[-2] assert "f_one" in stack[-3] - def test_short_stack_limit(self): + def test_short_stack_limit(self) -> None: stack = f_one(limit=5).splitlines() assert len(stack) == 5 - def test_short_stack_skip(self): + def test_short_stack_skip(self) -> None: stack = f_one(skip=1).splitlines() assert "f_two" in stack[-1] diff --git a/tests/test_execfile.py b/tests/test_execfile.py index e1db7bb5..229d8d95 100644 --- a/tests/test_execfile.py +++ b/tests/test_execfile.py @@ -12,6 +12,8 @@ import py_compile import re import sys +from typing import Any, Generator + import pytest from coverage.exceptions import NoCode, NoSource, _ExceptionDuringRun @@ -27,12 +29,12 @@ class RunFileTest(CoverageTest): """Test cases for `run_python_file`.""" @pytest.fixture(autouse=True) - def clean_up(self): + def clean_up(self) -> Generator[None, None, None]: """These tests all run in-process. Clean up global changes.""" yield sys.excepthook = sys.__excepthook__ - def test_run_python_file(self): + def test_run_python_file(self) -> None: run_python_file([TRY_EXECFILE, "arg1", "arg2"]) mod_globs = json.loads(self.stdout()) @@ -58,7 +60,7 @@ class RunFileTest(CoverageTest): # __builtins__ should have the right values, like open(). assert mod_globs['__builtins__.has_open'] is True - def test_no_extra_file(self): + def test_no_extra_file(self) -> None: # Make sure that running a file doesn't create an extra compiled file. self.make_file("xxx", """\ desc = "a non-.py file!" @@ -68,7 +70,7 @@ class RunFileTest(CoverageTest): run_python_file(["xxx"]) assert os.listdir(".") == ["xxx"] - def test_universal_newlines(self): + def test_universal_newlines(self) -> None: # Make sure we can read any sort of line ending. pylines = """# try newlines|print('Hello, world!')|""".split('|') for nl in ('\n', '\r\n', '\r'): @@ -77,7 +79,7 @@ class RunFileTest(CoverageTest): run_python_file(['nl.py']) assert self.stdout() == "Hello, world!\n"*3 - def test_missing_final_newline(self): + def test_missing_final_newline(self) -> None: # Make sure we can deal with a Python file with no final newline. self.make_file("abrupt.py", """\ if 1: @@ -90,25 +92,25 @@ class RunFileTest(CoverageTest): run_python_file(["abrupt.py"]) assert self.stdout() == "a is 1\n" - def test_no_such_file(self): + def test_no_such_file(self) -> None: path = python_reported_file('xyzzy.py') msg = re.escape(f"No file to run: '{path}'") with pytest.raises(NoSource, match=msg): run_python_file(["xyzzy.py"]) - def test_directory_with_main(self): + def test_directory_with_main(self) -> None: self.make_file("with_main/__main__.py", """\ print("I am __main__") """) run_python_file(["with_main"]) assert self.stdout() == "I am __main__\n" - def test_directory_without_main(self): + def test_directory_without_main(self) -> None: self.make_file("without_main/__init__.py", "") with pytest.raises(NoSource, match="Can't find '__main__' module in 'without_main'"): run_python_file(["without_main"]) - def test_code_throws(self): + def test_code_throws(self) -> None: self.make_file("throw.py", """\ class MyException(Exception): pass @@ -129,7 +131,7 @@ class RunFileTest(CoverageTest): assert self.stdout() == "about to raise..\n" assert self.stderr() == "" - def test_code_exits(self): + def test_code_exits(self) -> None: self.make_file("exit.py", """\ import sys def f1(): @@ -148,7 +150,7 @@ class RunFileTest(CoverageTest): assert self.stdout() == "about to exit..\n" assert self.stderr() == "" - def test_excepthook_exit(self): + def test_excepthook_exit(self) -> None: self.make_file("excepthook_exit.py", """\ import sys @@ -165,7 +167,7 @@ class RunFileTest(CoverageTest): cov_out = self.stdout() assert cov_out == "in excepthook\n" - def test_excepthook_throw(self): + def test_excepthook_throw(self) -> None: self.make_file("excepthook_throw.py", """\ import sys @@ -193,7 +195,7 @@ class RunFileTest(CoverageTest): class RunPycFileTest(CoverageTest): """Test cases for `run_python_file`.""" - def make_pyc(self, **kwargs): + def make_pyc(self, **kwargs: Any) -> str: """Create a .pyc file, and return the path to it.""" self.make_file("compiled.py", """\ def doit(): @@ -207,12 +209,12 @@ class RunPycFileTest(CoverageTest): # Find the .pyc file! return str(next(pathlib.Path(".").rglob("compiled*.pyc"))) - def test_running_pyc(self): + def test_running_pyc(self) -> None: pycfile = self.make_pyc() run_python_file([pycfile]) assert self.stdout() == "I am here!\n" - def test_running_pyo(self): + def test_running_pyo(self) -> None: pycfile = self.make_pyc() pyofile = re.sub(r"[.]pyc$", ".pyo", pycfile) assert pycfile != pyofile @@ -220,7 +222,7 @@ class RunPycFileTest(CoverageTest): run_python_file([pyofile]) assert self.stdout() == "I am here!\n" - def test_running_pyc_from_wrong_python(self): + def test_running_pyc_from_wrong_python(self) -> None: pycfile = self.make_pyc() # Jam Python 2.1 magic number into the .pyc file. @@ -234,18 +236,18 @@ class RunPycFileTest(CoverageTest): # In some environments, the pycfile persists and pollutes another test. os.remove(pycfile) - def test_running_hashed_pyc(self): + def test_running_hashed_pyc(self) -> None: pycfile = self.make_pyc(invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH) run_python_file([pycfile]) assert self.stdout() == "I am here!\n" - def test_no_such_pyc_file(self): + def test_no_such_pyc_file(self) -> None: path = python_reported_file('xyzzy.pyc') msg = re.escape(f"No file to run: '{path}'") with pytest.raises(NoCode, match=msg): run_python_file(["xyzzy.pyc"]) - def test_running_py_from_binary(self): + def test_running_py_from_binary(self) -> None: # Use make_file to get the bookkeeping. Ideally, it would # be able to write binary files. bf = self.make_file("binary") @@ -266,43 +268,43 @@ class RunModuleTest(UsingModulesMixin, CoverageTest): run_in_temp_dir = False - def test_runmod1(self): + def test_runmod1(self) -> None: run_python_module(["runmod1", "hello"]) out, err = self.stdouterr() assert out == "runmod1: passed hello\n" assert err == "" - def test_runmod2(self): + def test_runmod2(self) -> None: run_python_module(["pkg1.runmod2", "hello"]) out, err = self.stdouterr() assert out == "pkg1.__init__: pkg1\nrunmod2: passed hello\n" assert err == "" - def test_runmod3(self): + def test_runmod3(self) -> None: run_python_module(["pkg1.sub.runmod3", "hello"]) out, err = self.stdouterr() assert out == "pkg1.__init__: pkg1\nrunmod3: passed hello\n" assert err == "" - def test_pkg1_main(self): + def test_pkg1_main(self) -> None: run_python_module(["pkg1", "hello"]) out, err = self.stdouterr() assert out == "pkg1.__init__: pkg1\npkg1.__main__: passed hello\n" assert err == "" - def test_pkg1_sub_main(self): + def test_pkg1_sub_main(self) -> None: run_python_module(["pkg1.sub", "hello"]) out, err = self.stdouterr() assert out == "pkg1.__init__: pkg1\npkg1.sub.__main__: passed hello\n" assert err == "" - def test_pkg1_init(self): + def test_pkg1_init(self) -> None: run_python_module(["pkg1.__init__", "wut?"]) out, err = self.stdouterr() assert out == "pkg1.__init__: pkg1\npkg1.__init__: __main__\n" assert err == "" - def test_no_such_module(self): + def test_no_such_module(self) -> None: with pytest.raises(NoSource, match="No module named '?i_dont_exist'?"): run_python_module(["i_dont_exist"]) with pytest.raises(NoSource, match="No module named '?i'?"): @@ -310,6 +312,6 @@ class RunModuleTest(UsingModulesMixin, CoverageTest): with pytest.raises(NoSource, match="No module named '?i'?"): run_python_module(["i.dont.exist"]) - def test_no_main(self): + def test_no_main(self) -> None: with pytest.raises(NoSource): run_python_module(["pkg2", "hi"]) diff --git a/tests/test_filereporter.py b/tests/test_filereporter.py index 227cc458..59335309 100644 --- a/tests/test_filereporter.py +++ b/tests/test_filereporter.py @@ -20,7 +20,7 @@ class FileReporterTest(UsingModulesMixin, CoverageTest): run_in_temp_dir = False - def test_filenames(self): + def test_filenames(self) -> None: acu = PythonFileReporter("aa/afile.py") bcu = PythonFileReporter("aa/bb/bfile.py") ccu = PythonFileReporter("aa/bb/cc/cfile.py") @@ -31,7 +31,7 @@ class FileReporterTest(UsingModulesMixin, CoverageTest): assert bcu.source() == "# bfile.py\n" assert ccu.source() == "# cfile.py\n" - def test_odd_filenames(self): + def test_odd_filenames(self) -> None: acu = PythonFileReporter("aa/afile.odd.py") bcu = PythonFileReporter("aa/bb/bfile.odd.py") b2cu = PythonFileReporter("aa/bb.odd/bfile.py") @@ -42,7 +42,7 @@ class FileReporterTest(UsingModulesMixin, CoverageTest): assert bcu.source() == "# bfile.odd.py\n" assert b2cu.source() == "# bfile.py\n" - def test_modules(self): + def test_modules(self) -> None: import aa import aa.bb import aa.bb.cc @@ -57,7 +57,7 @@ class FileReporterTest(UsingModulesMixin, CoverageTest): assert bcu.source() == "# bb\n" assert ccu.source() == "" # yes, empty - def test_module_files(self): + def test_module_files(self) -> None: import aa.afile import aa.bb.bfile import aa.bb.cc.cfile @@ -72,7 +72,7 @@ class FileReporterTest(UsingModulesMixin, CoverageTest): assert bcu.source() == "# bfile.py\n" assert ccu.source() == "# cfile.py\n" - def test_comparison(self): + def test_comparison(self) -> None: acu = FileReporter("aa/afile.py") acu2 = FileReporter("aa/afile.py") zcu = FileReporter("aa/zfile.py") @@ -83,7 +83,7 @@ class FileReporterTest(UsingModulesMixin, CoverageTest): assert acu < bcu and acu <= bcu and acu != bcu assert bcu > acu and bcu >= acu and bcu != acu - def test_zipfile(self): + def test_zipfile(self) -> None: sys.path.append("tests/zip1.zip") # Test that we can get files out of zipfiles, and read their source files. diff --git a/tests/test_files.py b/tests/test_files.py index 2d029a04..ff02e0e9 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -7,6 +7,8 @@ import itertools import os import os.path import re + +from typing import Any, Generator, Iterable, List from unittest import mock import pytest @@ -17,6 +19,7 @@ from coverage.files import ( GlobMatcher, ModuleMatcher, PathAliases, TreeMatcher, abs_file, actual_path, find_python_files, flat_rootname, globs_to_regex, ) +from coverage.types import Protocol from tests.coveragetest import CoverageTest from tests.helpers import os_sep @@ -25,11 +28,11 @@ from tests.helpers import os_sep class FilesTest(CoverageTest): """Tests of coverage.files.""" - def abs_path(self, p): + def abs_path(self, p: str) -> str: """Return the absolute path for `p`.""" return os.path.join(abs_file(os.getcwd()), os.path.normpath(p)) - def test_simple(self): + def test_simple(self) -> None: self.make_file("hello.py") files.set_relative_directory() assert files.relative_filename("hello.py") == "hello.py" @@ -37,7 +40,7 @@ class FilesTest(CoverageTest): assert a != "hello.py" assert files.relative_filename(a) == "hello.py" - def test_peer_directories(self): + def test_peer_directories(self) -> None: self.make_file("sub/proj1/file1.py") self.make_file("sub/proj2/file2.py") a1 = self.abs_path("sub/proj1/file1.py") @@ -48,7 +51,7 @@ class FilesTest(CoverageTest): assert files.relative_filename(a1) == "file1.py" assert files.relative_filename(a2) == a2 - def test_filepath_contains_absolute_prefix_twice(self): + def test_filepath_contains_absolute_prefix_twice(self) -> None: # https://github.com/nedbat/coveragepy/issues/194 # Build a path that has two pieces matching the absolute path prefix. # Technically, this test doesn't do that on Windows, but drive @@ -59,7 +62,7 @@ class FilesTest(CoverageTest): rel = os.path.join('sub', trick, 'file1.py') assert files.relative_filename(abs_file(rel)) == rel - def test_canonical_filename_ensure_cache_hit(self): + def test_canonical_filename_ensure_cache_hit(self) -> None: self.make_file("sub/proj1/file1.py") d = actual_path(self.abs_path("sub/proj1")) os.chdir(d) @@ -76,7 +79,7 @@ class FilesTest(CoverageTest): ("X:\\", "\\"), ] ) - def test_relative_dir_for_root(self, curdir, sep): + def test_relative_dir_for_root(self, curdir: str, sep: str) -> None: with mock.patch.object(files.os, 'curdir', new=curdir): with mock.patch.object(files.os, 'sep', new=sep): with mock.patch('coverage.files.os.path.normcase', return_value=curdir): @@ -95,7 +98,7 @@ class FilesTest(CoverageTest): ("src/files.pex", "src/files.pex/zipfiles/files.zip/foo.py", True), ] ) - def test_source_exists(self, to_make, to_check, answer): + def test_source_exists(self, to_make: str, to_check: str, answer: bool) -> None: # source_exists won't look inside the zipfile, so it's fine to make # an empty file with the zipfile name. self.make_file(to_make, "") @@ -122,13 +125,17 @@ class FilesTest(CoverageTest): "d_e597dfacb73a23d5_my_program_py" ), ]) -def test_flat_rootname(original, flat): +def test_flat_rootname(original: str, flat: str) -> None: assert flat_rootname(original) == flat def globs_to_regex_params( - patterns, case_insensitive=False, partial=False, matches=(), nomatches=(), -): + patterns: Iterable[str], + case_insensitive: bool=False, + partial: bool=False, + matches: Iterable[str]=(), + nomatches: Iterable[str]=(), +) -> Generator[Any, None, None]: """Generate parameters for `test_globs_to_regex`. `patterns`, `case_insensitive`, and `partial` are arguments for @@ -242,11 +249,14 @@ def globs_to_regex_params( ), ])) ) -def test_globs_to_regex(patterns, case_insensitive, partial, text, result): +def test_globs_to_regex( + patterns: Iterable[str], + case_insensitive: bool, + partial: bool, + text: str, + result: bool, +) -> None: regex = globs_to_regex(patterns, case_insensitive=case_insensitive, partial=partial) - print(patterns) - print(regex) - print(text) assert bool(regex.match(text)) == result @@ -261,26 +271,33 @@ def test_globs_to_regex(patterns, case_insensitive, partial, text, result): ("x/**a/b.py", "**a"), ("x/**/**/b.py", "**/**"), ]) -def test_invalid_globs(pattern, bad_word): +def test_invalid_globs(pattern: str, bad_word: str) -> None: msg = f"File pattern can't include {bad_word!r}" with pytest.raises(ConfigError, match=re.escape(msg)): globs_to_regex([pattern]) +class TMatcher(Protocol): + """The shape all Matchers have.""" + + def match(self, s: str) -> bool: + """Does this string match?""" + + class MatcherTest(CoverageTest): """Tests of file matchers.""" - def setUp(self): + def setUp(self) -> None: super().setUp() files.set_relative_directory() - def assertMatches(self, matcher, filepath, matches): + def assertMatches(self, matcher: TMatcher, filepath: str, matches: bool) -> None: """The `matcher` should agree with `matches` about `filepath`.""" canonical = files.canonical_filename(filepath) msg = f"File {filepath} should have matched as {matches}" assert matches == matcher.match(canonical), msg - def test_tree_matcher(self): + def test_tree_matcher(self) -> None: case_folding = env.WINDOWS matches_to_try = [ (self.make_file("sub/file1.py"), True), @@ -302,7 +319,7 @@ class MatcherTest(CoverageTest): for filepath, matches in matches_to_try: self.assertMatches(tm, filepath, matches) - def test_module_matcher(self): + def test_module_matcher(self) -> None: matches_to_try = [ ('test', True), ('trash', False), @@ -325,7 +342,7 @@ class MatcherTest(CoverageTest): for modulename, matches in matches_to_try: assert mm.match(modulename) == matches, modulename - def test_glob_matcher(self): + def test_glob_matcher(self) -> None: matches_to_try = [ (self.make_file("sub/file1.py"), True), (self.make_file("sub/file2.c"), False), @@ -338,7 +355,7 @@ class MatcherTest(CoverageTest): for filepath, matches in matches_to_try: self.assertMatches(fnm, filepath, matches) - def test_glob_matcher_overload(self): + def test_glob_matcher_overload(self) -> None: fnm = GlobMatcher(["*x%03d*.txt" % i for i in range(500)]) self.assertMatches(fnm, "x007foo.txt", True) self.assertMatches(fnm, "x123foo.txt", True) @@ -346,7 +363,7 @@ class MatcherTest(CoverageTest): self.assertMatches(fnm, "x499.txt", True) self.assertMatches(fnm, "x500.txt", False) - def test_glob_windows_paths(self): + def test_glob_windows_paths(self) -> None: # We should be able to match Windows paths even if we are running on # a non-Windows OS. fnm = GlobMatcher(["*/foo.py"]) @@ -356,9 +373,9 @@ class MatcherTest(CoverageTest): @pytest.fixture(params=[False, True], name="rel_yn") -def relative_setting(request): +def relative_setting(request: pytest.FixtureRequest) -> bool: """Parameterized fixture to choose whether PathAliases is relative or not.""" - return request.param + return request.param # type: ignore[no-any-return] class PathAliasesTest(CoverageTest): @@ -366,7 +383,7 @@ class PathAliasesTest(CoverageTest): run_in_temp_dir = False - def assert_mapped(self, aliases, inp, out): + def assert_mapped(self, aliases: PathAliases, inp: str, out: str) -> None: """Assert that `inp` mapped through `aliases` produces `out`. If the aliases are not relative, then `out` is canonicalized first, @@ -380,20 +397,20 @@ class PathAliasesTest(CoverageTest): expected = files.canonical_filename(out) assert mapped == expected - def assert_unchanged(self, aliases, inp, exists=True): + def assert_unchanged(self, aliases: PathAliases, inp: str, exists: bool=True) -> None: """Assert that `inp` mapped through `aliases` is unchanged.""" assert aliases.map(inp, exists=lambda p: exists) == inp - def test_noop(self, rel_yn): + def test_noop(self, rel_yn: bool) -> None: aliases = PathAliases(relative=rel_yn) self.assert_unchanged(aliases, '/ned/home/a.py') - def test_nomatch(self, rel_yn): + def test_nomatch(self, rel_yn: bool) -> None: aliases = PathAliases(relative=rel_yn) aliases.add('/home/*/src', './mysrc') self.assert_unchanged(aliases, '/home/foo/a.py') - def test_wildcard(self, rel_yn): + def test_wildcard(self, rel_yn: bool) -> None: aliases = PathAliases(relative=rel_yn) aliases.add('/ned/home/*/src', './mysrc') self.assert_mapped(aliases, '/ned/home/foo/src/a.py', './mysrc/a.py') @@ -402,24 +419,24 @@ class PathAliasesTest(CoverageTest): aliases.add('/ned/home/*/src/', './mysrc') self.assert_mapped(aliases, '/ned/home/foo/src/a.py', './mysrc/a.py') - def test_no_accidental_match(self, rel_yn): + def test_no_accidental_match(self, rel_yn: bool) -> None: aliases = PathAliases(relative=rel_yn) aliases.add('/home/*/src', './mysrc') self.assert_unchanged(aliases, '/home/foo/srcetc') - def test_no_map_if_not_exist(self, rel_yn): + def test_no_map_if_not_exist(self, rel_yn: bool) -> None: aliases = PathAliases(relative=rel_yn) aliases.add('/ned/home/*/src', './mysrc') self.assert_unchanged(aliases, '/ned/home/foo/src/a.py', exists=False) self.assert_unchanged(aliases, 'foo/src/a.py', exists=False) - def test_no_dotslash(self, rel_yn): + def test_no_dotslash(self, rel_yn: bool) -> None: # The result shouldn't start with "./" if the map result didn't. aliases = PathAliases(relative=rel_yn) aliases.add('*/project', '.') self.assert_mapped(aliases, '/ned/home/project/src/a.py', os_sep('src/a.py')) - def test_relative_pattern(self): + def test_relative_pattern(self) -> None: aliases = PathAliases(relative=True) aliases.add(".tox/*/site-packages", "src") self.assert_mapped( @@ -428,9 +445,9 @@ class PathAliasesTest(CoverageTest): os_sep("src/proj/a.py"), ) - def test_multiple_patterns(self, rel_yn): + def test_multiple_patterns(self, rel_yn: bool) -> None: # also test the debugfn... - msgs = [] + msgs: List[str] = [] aliases = PathAliases(debugfn=msgs.append, relative=rel_yn) aliases.add('/home/*/src', './mysrc') aliases.add('/lib/*/libsrc', './mylib') @@ -466,20 +483,20 @@ class PathAliasesTest(CoverageTest): "/ned/home/*/", "/ned/home/*/*/", ]) - def test_cant_have_wildcard_at_end(self, badpat): + def test_cant_have_wildcard_at_end(self, badpat: str) -> None: aliases = PathAliases() msg = "Pattern must not end with wildcards." with pytest.raises(ConfigError, match=msg): aliases.add(badpat, "fooey") - def test_no_accidental_munging(self): + def test_no_accidental_munging(self) -> None: aliases = PathAliases() aliases.add(r'c:\Zoo\boo', 'src/') aliases.add('/home/ned$', 'src/') self.assert_mapped(aliases, r'c:\Zoo\boo\foo.py', 'src/foo.py') self.assert_mapped(aliases, r'/home/ned$/foo.py', 'src/foo.py') - def test_paths_are_os_corrected(self, rel_yn): + def test_paths_are_os_corrected(self, rel_yn: bool) -> None: aliases = PathAliases(relative=rel_yn) aliases.add('/home/ned/*/src', './mysrc') aliases.add(r'c:\ned\src', './mysrc') @@ -500,7 +517,7 @@ class PathAliasesTest(CoverageTest): lin_win_paths = [[lin, win], [win, lin]] @pytest.mark.parametrize("paths", lin_win_paths) - def test_windows_on_linux(self, paths, rel_yn): + def test_windows_on_linux(self, paths: Iterable[str], rel_yn: bool) -> None: # https://github.com/nedbat/coveragepy/issues/618 aliases = PathAliases(relative=rel_yn) for path in paths: @@ -512,7 +529,7 @@ class PathAliasesTest(CoverageTest): ) @pytest.mark.parametrize("paths", lin_win_paths) - def test_linux_on_windows(self, paths, rel_yn): + def test_linux_on_windows(self, paths: Iterable[str], rel_yn: bool) -> None: # https://github.com/nedbat/coveragepy/issues/618 aliases = PathAliases(relative=rel_yn) for path in paths: @@ -524,7 +541,7 @@ class PathAliasesTest(CoverageTest): ) @pytest.mark.parametrize("paths", lin_win_paths) - def test_relative_windows_on_linux(self, paths): + def test_relative_windows_on_linux(self, paths: Iterable[str]) -> None: # https://github.com/nedbat/coveragepy/issues/991 aliases = PathAliases(relative=True) for path in paths: @@ -536,7 +553,7 @@ class PathAliasesTest(CoverageTest): ) @pytest.mark.parametrize("paths", lin_win_paths) - def test_relative_linux_on_windows(self, paths): + def test_relative_linux_on_windows(self, paths: Iterable[str]) -> None: # https://github.com/nedbat/coveragepy/issues/991 aliases = PathAliases(relative=True) for path in paths: @@ -548,7 +565,7 @@ class PathAliasesTest(CoverageTest): ) @pytest.mark.skipif(env.WINDOWS, reason="This test assumes Unix file system") - def test_implicit_relative_windows_on_linux(self): + def test_implicit_relative_windows_on_linux(self) -> None: # https://github.com/nedbat/coveragepy/issues/991 aliases = PathAliases(relative=True) self.assert_mapped( @@ -558,7 +575,7 @@ class PathAliasesTest(CoverageTest): ) @pytest.mark.skipif(not env.WINDOWS, reason="This test assumes Windows file system") - def test_implicit_relative_linux_on_windows(self): + def test_implicit_relative_linux_on_windows(self) -> None: # https://github.com/nedbat/coveragepy/issues/991 aliases = PathAliases(relative=True) self.assert_mapped( @@ -567,7 +584,7 @@ class PathAliasesTest(CoverageTest): r"project\module\tests\file.py", ) - def test_multiple_wildcard(self, rel_yn): + def test_multiple_wildcard(self, rel_yn: bool) -> None: aliases = PathAliases(relative=rel_yn) aliases.add('/home/jenkins/*/a/*/b/*/django', './django') self.assert_mapped( @@ -576,7 +593,7 @@ class PathAliasesTest(CoverageTest): './django/foo/bar.py', ) - def test_windows_root_paths(self, rel_yn): + def test_windows_root_paths(self, rel_yn: bool) -> None: aliases = PathAliases(relative=rel_yn) aliases.add('X:\\', '/tmp/src') self.assert_mapped( @@ -590,7 +607,7 @@ class PathAliasesTest(CoverageTest): "/tmp/src/file.py", ) - def test_leading_wildcard(self, rel_yn): + def test_leading_wildcard(self, rel_yn: bool) -> None: aliases = PathAliases(relative=rel_yn) aliases.add('*/d1', './mysrc1') aliases.add('*/d2', './mysrc2') @@ -598,7 +615,7 @@ class PathAliasesTest(CoverageTest): self.assert_mapped(aliases, '/foo/bar/d2/y.py', './mysrc2/y.py') @pytest.mark.parametrize("dirname", [".", "..", "../other", "/"]) - def test_dot(self, dirname): + def test_dot(self, dirname: str) -> None: if env.WINDOWS and dirname == "/": # The root test case was added for the manylinux Docker images, # and I'm not sure how it should work on Windows, so skip it. @@ -616,7 +633,7 @@ class PathAliasesTest(CoverageTest): class PathAliasesRealFilesTest(CoverageTest): """Tests for coverage/files.py:PathAliases using real files.""" - def test_aliasing_zip_files(self): + def test_aliasing_zip_files(self) -> None: self.make_file("src/zipfiles/code.zip", "fake zip, doesn't matter") aliases = PathAliases() aliases.add("*/d1", "./src") @@ -629,7 +646,7 @@ class PathAliasesRealFilesTest(CoverageTest): class FindPythonFilesTest(CoverageTest): """Tests of `find_python_files`.""" - def test_find_python_files(self): + def test_find_python_files(self) -> None: self.make_file("sub/a.py") self.make_file("sub/b.py") self.make_file("sub/x.c") # nope: not .py @@ -645,7 +662,7 @@ class FindPythonFilesTest(CoverageTest): "sub/windows.pyw", ]) - def test_find_python_files_include_namespace_packages(self): + def test_find_python_files_include_namespace_packages(self) -> None: self.make_file("sub/a.py") self.make_file("sub/b.py") self.make_file("sub/x.c") # nope: not .py @@ -669,5 +686,5 @@ class WindowsFileTest(CoverageTest): run_in_temp_dir = False - def test_actual_path(self): + def test_actual_path(self) -> None: assert actual_path(r'c:\Windows') == actual_path(r'C:\wINDOWS') diff --git a/tests/test_summary.py b/tests/test_summary.py index f3c7ed3f..15c75348 100644 --- a/tests/test_summary.py +++ b/tests/test_summary.py @@ -22,7 +22,7 @@ from coverage.data import CoverageData from coverage.exceptions import ConfigError, NoDataError, NotPython from coverage.files import abs_file from coverage.summary import SummaryReporter -from coverage.types import TConfigValue +from coverage.types import TConfigValueIn from tests.coveragetest import CoverageTest, TESTS_DIR, UsingModulesMixin from tests.helpers import assert_coverage_warnings @@ -900,7 +900,7 @@ class SummaryReporterConfigurationTest(CoverageTest): source += " a = 2\n" * dont_run self.make_file(filename, source) - def get_summary_text(self, *options: Tuple[str, TConfigValue]) -> str: + def get_summary_text(self, *options: Tuple[str, TConfigValueIn]) -> str: """Get text output from the SummaryReporter. The arguments are tuples: (name, value) for Coverage.set_option. |