Coverage for tests / unit / tools / mypy / test_mypy_plugin.py: 100%
35 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Unit tests for mypy plugin."""
3from __future__ import annotations
5from typing import TYPE_CHECKING
7import pytest
8from assertpy import assert_that
10from lintro.tools.definitions.mypy import (
11 MYPY_DEFAULT_EXCLUDE_PATTERNS,
12 _regex_to_glob,
13 _split_config_values,
14)
16if TYPE_CHECKING:
17 from lintro.tools.definitions.mypy import MypyPlugin
20# Tests for _split_config_values helper
23@pytest.mark.parametrize(
24 ("input_value", "expected"),
25 [
26 ("a,b,c", ["a", "b", "c"]),
27 ("a\nb\nc", ["a", "b", "c"]),
28 ("a,b\nc,d", ["a", "b", "c", "d"]),
29 (" a , b ", ["a", "b"]),
30 ("a,,b,", ["a", "b"]),
31 ],
32 ids=[
33 "comma_separated",
34 "newline_separated",
35 "mixed_separators",
36 "strips_whitespace",
37 "filters_empty",
38 ],
39)
40def test_split_config_values(input_value: str, expected: list[str]) -> None:
41 """Split config values correctly.
43 Args:
44 input_value: The input string to split.
45 expected: The expected list of split values.
46 """
47 result = _split_config_values(input_value)
48 assert_that(result).is_equal_to(expected)
51# Tests for _regex_to_glob helper
54@pytest.mark.parametrize(
55 ("input_pattern", "expected"),
56 [
57 ("^test$", "test"),
58 ("test.*", "test*"),
59 ("build/", "build/**"),
60 ("^.*/test_samples/.*$", "*/test_samples/*"),
61 ],
62 ids=[
63 "strips_anchors",
64 "converts_wildcard",
65 "adds_glob_for_directory",
66 "complex_pattern",
67 ],
68)
69def test_regex_to_glob(input_pattern: str, expected: str) -> None:
70 """Convert regex patterns to glob patterns.
72 Args:
73 input_pattern: The regex pattern to convert.
74 expected: The expected glob pattern.
75 """
76 result = _regex_to_glob(input_pattern)
77 assert_that(result).is_equal_to(expected)
80@pytest.mark.parametrize(
81 ("option_name", "option_value"),
82 [
83 ("strict", True),
84 ("ignore_missing_imports", False),
85 ("python_version", "3.10"),
86 ("config_file", "mypy.ini"),
87 ("cache_dir", ".mypy_cache"),
88 ],
89 ids=[
90 "strict",
91 "ignore_missing_imports",
92 "python_version",
93 "config_file",
94 "cache_dir",
95 ],
96)
97def test_set_options_valid(
98 mypy_plugin: MypyPlugin,
99 option_name: str,
100 option_value: object,
101) -> None:
102 """Set valid options correctly.
104 Args:
105 mypy_plugin: The MypyPlugin instance to test.
106 option_name: The name of the option to set.
107 option_value: The value to set for the option.
108 """
109 mypy_plugin.set_options(**{option_name: option_value}) # type: ignore[arg-type]
110 assert_that(mypy_plugin.options.get(option_name)).is_equal_to(option_value)
113# Tests for MypyPlugin.set_options method - invalid types
116@pytest.mark.parametrize(
117 ("option_name", "invalid_value", "error_match"),
118 [
119 ("strict", "yes", "strict must be a boolean"),
120 ("ignore_missing_imports", "yes", "ignore_missing_imports must be a boolean"),
121 ("python_version", 310, "python_version must be a string"),
122 ("config_file", 123, "config_file must be a string"),
123 ("cache_dir", 123, "cache_dir must be a string"),
124 ],
125 ids=[
126 "invalid_strict_type",
127 "invalid_ignore_missing_imports_type",
128 "invalid_python_version_type",
129 "invalid_config_file_type",
130 "invalid_cache_dir_type",
131 ],
132)
133def test_set_options_invalid_type(
134 mypy_plugin: MypyPlugin,
135 option_name: str,
136 invalid_value: object,
137 error_match: str,
138) -> None:
139 """Raise ValueError for invalid option types.
141 Args:
142 mypy_plugin: The MypyPlugin instance to test.
143 option_name: The name of the option to test.
144 invalid_value: An invalid value for the option.
145 error_match: The expected error message pattern.
146 """
147 with pytest.raises(ValueError, match=error_match):
148 mypy_plugin.set_options(**{option_name: invalid_value}) # type: ignore[arg-type]
151# Tests for MypyPlugin._build_effective_excludes method
154def test_build_effective_excludes_includes_defaults(mypy_plugin: MypyPlugin) -> None:
155 """Include default exclude patterns.
157 Args:
158 mypy_plugin: The MypyPlugin instance to test.
159 """
160 result = mypy_plugin._build_effective_excludes(None)
162 for pattern in MYPY_DEFAULT_EXCLUDE_PATTERNS:
163 assert_that(pattern in result).is_true()
166def test_build_effective_excludes_adds_configured(mypy_plugin: MypyPlugin) -> None:
167 """Add configured exclude patterns.
169 Args:
170 mypy_plugin: The MypyPlugin instance to test.
171 """
172 result = mypy_plugin._build_effective_excludes("custom_dir/")
174 assert_that("custom_dir/**" in result).is_true()
177def test_build_effective_excludes_handles_list(mypy_plugin: MypyPlugin) -> None:
178 """Handle list of exclude patterns.
180 Args:
181 mypy_plugin: The MypyPlugin instance to test.
182 """
183 result = mypy_plugin._build_effective_excludes(["dir1/", "dir2/"])
185 assert_that("dir1/**" in result).is_true()
186 assert_that("dir2/**" in result).is_true()
189def test_build_effective_excludes_converts_regex(mypy_plugin: MypyPlugin) -> None:
190 """Convert regex patterns to globs.
192 Args:
193 mypy_plugin: The MypyPlugin instance to test.
194 """
195 result = mypy_plugin._build_effective_excludes(["^tests/.*$"])
197 assert_that("tests/*" in result).is_true()