Coverage for tests / unit / tools / test_tool_definitions.py: 100%
40 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"""Consolidated tests for all tool definitions.
3This module provides parametrized tests to verify that all tool plugins
4have correct definition properties. This ensures consistency across the
5codebase and catches definition errors early.
6"""
8from __future__ import annotations
10from typing import Any
12import pytest
13from assertpy import assert_that
15from lintro.enums.tool_name import ToolName
17# Tool specifications: (name, class, timeout, priority, can_fix)
18# Some tools need special initialization (mocked dependencies)
19TOOL_SPECS = [
20 # (tool_name, module_path, class_name, timeout, priority, can_fix)
21 (ToolName.RUFF, "lintro.tools.definitions.ruff", "RuffPlugin", 30, 85, True),
22 (ToolName.BLACK, "lintro.tools.definitions.black", "BlackPlugin", 30, 90, True),
23 (ToolName.CLIPPY, "lintro.tools.definitions.clippy", "ClippyPlugin", 120, 85, True),
24 (ToolName.MYPY, "lintro.tools.definitions.mypy", "MypyPlugin", 60, 82, False),
25 (
26 ToolName.YAMLLINT,
27 "lintro.tools.definitions.yamllint",
28 "YamllintPlugin",
29 15,
30 40,
31 False,
32 ),
33 (
34 ToolName.HADOLINT,
35 "lintro.tools.definitions.hadolint",
36 "HadolintPlugin",
37 30,
38 50,
39 False,
40 ),
41 (
42 ToolName.PYTEST,
43 "lintro.tools.definitions.pytest",
44 "PytestPlugin",
45 300,
46 90,
47 False,
48 ),
49 (
50 ToolName.MARKDOWNLINT,
51 "lintro.tools.definitions.markdownlint",
52 "MarkdownlintPlugin",
53 30,
54 30,
55 False,
56 ),
57 (
58 ToolName.ACTIONLINT,
59 "lintro.tools.definitions.actionlint",
60 "ActionlintPlugin",
61 30,
62 40,
63 False,
64 ),
65 (ToolName.BANDIT, "lintro.tools.definitions.bandit", "BanditPlugin", 30, 90, False),
66]
69def _create_plugin_instance(module_path: str, class_name: str) -> Any:
70 """Dynamically import and instantiate a plugin class.
72 Args:
73 module_path: Full module path to the plugin class.
74 class_name: Name of the plugin class.
76 Returns:
77 An instance of the plugin class.
78 """
79 import importlib
81 # Safe: module_path comes from hardcoded TOOL_SPECS, not user input
82 module = importlib.import_module(module_path) # nosemgrep: non-literal-import
83 plugin_class = getattr(module, class_name)
84 return plugin_class()
87# =============================================================================
88# Tests for tool definition properties
89# =============================================================================
92@pytest.mark.parametrize(
93 (
94 "tool_name",
95 "module_path",
96 "class_name",
97 "expected_timeout",
98 "expected_priority",
99 "expected_can_fix",
100 ),
101 TOOL_SPECS,
102 ids=[spec[0] for spec in TOOL_SPECS],
103)
104def test_tool_definition_name(
105 tool_name: str,
106 module_path: str,
107 class_name: str,
108 expected_timeout: int,
109 expected_priority: int,
110 expected_can_fix: bool,
111) -> None:
112 """Tool has correct name in definition.
114 Args:
115 tool_name: Name of the tool.
116 module_path: Module path containing the tool plugin.
117 class_name: Class name of the tool plugin.
118 expected_timeout: Expected timeout value for the tool.
119 expected_priority: Expected priority value for the tool.
120 expected_can_fix: Whether the tool can perform fixes.
121 """
122 plugin = _create_plugin_instance(module_path, class_name)
123 assert_that(plugin.definition.name).is_equal_to(tool_name)
126@pytest.mark.parametrize(
127 (
128 "tool_name",
129 "module_path",
130 "class_name",
131 "expected_timeout",
132 "expected_priority",
133 "expected_can_fix",
134 ),
135 TOOL_SPECS,
136 ids=[spec[0] for spec in TOOL_SPECS],
137)
138def test_tool_definition_has_description(
139 tool_name: str,
140 module_path: str,
141 class_name: str,
142 expected_timeout: int,
143 expected_priority: int,
144 expected_can_fix: bool,
145) -> None:
146 """Tool has non-empty description in definition.
148 Args:
149 tool_name: Name of the tool.
150 module_path: Module path containing the tool plugin.
151 class_name: Class name of the tool plugin.
152 expected_timeout: Expected timeout value for the tool.
153 expected_priority: Expected priority value for the tool.
154 expected_can_fix: Whether the tool can perform fixes.
155 """
156 plugin = _create_plugin_instance(module_path, class_name)
157 assert_that(plugin.definition.description).is_not_empty()
160@pytest.mark.parametrize(
161 (
162 "tool_name",
163 "module_path",
164 "class_name",
165 "expected_timeout",
166 "expected_priority",
167 "expected_can_fix",
168 ),
169 TOOL_SPECS,
170 ids=[spec[0] for spec in TOOL_SPECS],
171)
172def test_tool_definition_timeout(
173 tool_name: str,
174 module_path: str,
175 class_name: str,
176 expected_timeout: int,
177 expected_priority: int,
178 expected_can_fix: bool,
179) -> None:
180 """Tool has correct default timeout.
182 Args:
183 tool_name: Name of the tool.
184 module_path: Module path containing the tool plugin.
185 class_name: Class name of the tool plugin.
186 expected_timeout: Expected timeout value for the tool.
187 expected_priority: Expected priority value for the tool.
188 expected_can_fix: Whether the tool can perform fixes.
189 """
190 plugin = _create_plugin_instance(module_path, class_name)
191 assert_that(plugin.definition.default_timeout).is_equal_to(expected_timeout)
194@pytest.mark.parametrize(
195 (
196 "tool_name",
197 "module_path",
198 "class_name",
199 "expected_timeout",
200 "expected_priority",
201 "expected_can_fix",
202 ),
203 TOOL_SPECS,
204 ids=[spec[0] for spec in TOOL_SPECS],
205)
206def test_tool_definition_priority(
207 tool_name: str,
208 module_path: str,
209 class_name: str,
210 expected_timeout: int,
211 expected_priority: int,
212 expected_can_fix: bool,
213) -> None:
214 """Tool has correct priority.
216 Args:
217 tool_name: Name of the tool.
218 module_path: Module path containing the tool plugin.
219 class_name: Class name of the tool plugin.
220 expected_timeout: Expected timeout value for the tool.
221 expected_priority: Expected priority value for the tool.
222 expected_can_fix: Whether the tool can perform fixes.
223 """
224 plugin = _create_plugin_instance(module_path, class_name)
225 assert_that(plugin.definition.priority).is_equal_to(expected_priority)
228@pytest.mark.parametrize(
229 (
230 "tool_name",
231 "module_path",
232 "class_name",
233 "expected_timeout",
234 "expected_priority",
235 "expected_can_fix",
236 ),
237 TOOL_SPECS,
238 ids=[spec[0] for spec in TOOL_SPECS],
239)
240def test_tool_definition_can_fix(
241 tool_name: str,
242 module_path: str,
243 class_name: str,
244 expected_timeout: int,
245 expected_priority: int,
246 expected_can_fix: bool,
247) -> None:
248 """Tool has correct can_fix value.
250 Args:
251 tool_name: Name of the tool.
252 module_path: Module path containing the tool plugin.
253 class_name: Class name of the tool plugin.
254 expected_timeout: Expected timeout value for the tool.
255 expected_priority: Expected priority value for the tool.
256 expected_can_fix: Whether the tool can perform fixes.
257 """
258 plugin = _create_plugin_instance(module_path, class_name)
259 assert_that(plugin.definition.can_fix).is_equal_to(expected_can_fix)
262# =============================================================================
263# Tests for tool definition validation
264# =============================================================================
267@pytest.mark.parametrize(
268 (
269 "tool_name",
270 "module_path",
271 "class_name",
272 "expected_timeout",
273 "expected_priority",
274 "expected_can_fix",
275 ),
276 TOOL_SPECS,
277 ids=[spec[0] for spec in TOOL_SPECS],
278)
279def test_tool_has_file_patterns(
280 tool_name: str,
281 module_path: str,
282 class_name: str,
283 expected_timeout: int,
284 expected_priority: int,
285 expected_can_fix: bool,
286) -> None:
287 """Tool has non-empty file patterns.
289 Args:
290 tool_name: Name of the tool.
291 module_path: Module path containing the tool plugin.
292 class_name: Class name of the tool plugin.
293 expected_timeout: Expected timeout value for the tool.
294 expected_priority: Expected priority value for the tool.
295 expected_can_fix: Whether the tool can perform fixes.
296 """
297 plugin = _create_plugin_instance(module_path, class_name)
298 assert_that(plugin.definition.file_patterns).is_not_empty()
301@pytest.mark.parametrize(
302 (
303 "tool_name",
304 "module_path",
305 "class_name",
306 "expected_timeout",
307 "expected_priority",
308 "expected_can_fix",
309 ),
310 TOOL_SPECS,
311 ids=[spec[0] for spec in TOOL_SPECS],
312)
313def test_tool_has_default_options(
314 tool_name: str,
315 module_path: str,
316 class_name: str,
317 expected_timeout: int,
318 expected_priority: int,
319 expected_can_fix: bool,
320) -> None:
321 """Tool has default options dictionary.
323 Args:
324 tool_name: Name of the tool.
325 module_path: Module path containing the tool plugin.
326 class_name: Class name of the tool plugin.
327 expected_timeout: Expected timeout value for the tool.
328 expected_priority: Expected priority value for the tool.
329 expected_can_fix: Whether the tool can perform fixes.
330 """
331 plugin = _create_plugin_instance(module_path, class_name)
332 assert_that(plugin.definition.default_options).is_not_none()
333 assert_that(plugin.definition.default_options).contains_key("timeout")