Coverage for tests / unit / tools / pytest_tool / test_pytest_handlers.py: 100%
131 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"""Tests for lintro.tools.implementations.pytest.pytest_handlers module."""
3from __future__ import annotations
5from typing import TYPE_CHECKING
6from unittest.mock import MagicMock, patch
8from assertpy import assert_that
10from lintro.tools.implementations.pytest.pytest_handlers import (
11 handle_check_plugins,
12 handle_collect_only,
13 handle_fixture_info,
14 handle_list_fixtures,
15 handle_list_markers,
16 handle_list_plugins,
17 handle_parametrize_help,
18)
20if TYPE_CHECKING:
21 pass
24def _make_mock_tool(name: str = "pytest") -> MagicMock:
25 """Create a mock tool for testing.
27 Args:
28 name: Tool name for mock.
30 Returns:
31 MagicMock configured as a PytestPlugin.
32 """
33 mock_tool = MagicMock()
34 mock_tool.definition.name = name
35 mock_tool._get_executable_command.return_value = ["pytest"]
36 return mock_tool
39# =============================================================================
40# handle_list_plugins tests
41# =============================================================================
44@patch("lintro.tools.implementations.pytest.pytest_handlers.get_pytest_version_info")
45@patch("lintro.tools.implementations.pytest.pytest_handlers.list_installed_plugins")
46def test_handle_list_plugins_with_plugins(
47 mock_list: MagicMock,
48 mock_version: MagicMock,
49) -> None:
50 """handle_list_plugins lists installed plugins.
52 Args:
53 mock_list: Mock for list_installed_plugins.
54 mock_version: Mock for get_pytest_version_info.
55 """
56 mock_version.return_value = "pytest 7.4.0"
57 mock_list.return_value = [
58 {"name": "pytest-cov", "version": "4.1.0"},
59 {"name": "pytest-mock", "version": "3.11.1"},
60 ]
61 mock_tool = _make_mock_tool()
63 result = handle_list_plugins(mock_tool)
65 assert_that(result.success).is_true()
66 assert_that(result.output).contains("pytest 7.4.0")
67 assert_that(result.output).contains("Installed pytest plugins (2):")
68 assert_that(result.output).contains("pytest-cov (4.1.0)")
69 assert_that(result.output).contains("pytest-mock (3.11.1)")
72@patch("lintro.tools.implementations.pytest.pytest_handlers.get_pytest_version_info")
73@patch("lintro.tools.implementations.pytest.pytest_handlers.list_installed_plugins")
74def test_handle_list_plugins_no_plugins(
75 mock_list: MagicMock,
76 mock_version: MagicMock,
77) -> None:
78 """handle_list_plugins handles no plugins case.
80 Args:
81 mock_list: Mock for list_installed_plugins.
82 mock_version: Mock for get_pytest_version_info.
83 """
84 mock_version.return_value = "pytest 7.4.0"
85 mock_list.return_value = []
86 mock_tool = _make_mock_tool()
88 result = handle_list_plugins(mock_tool)
90 assert_that(result.success).is_true()
91 assert_that(result.output).contains("No pytest plugins found")
94# =============================================================================
95# handle_check_plugins tests
96# =============================================================================
99@patch("lintro.tools.implementations.pytest.pytest_handlers.check_plugin_installed")
100def test_handle_check_plugins_all_installed(mock_check: MagicMock) -> None:
101 """handle_check_plugins reports all installed.
103 Args:
104 mock_check: Mock for check_plugin_installed.
105 """
106 mock_check.return_value = True
107 mock_tool = _make_mock_tool()
109 result = handle_check_plugins(mock_tool, "pytest-cov, pytest-mock")
111 assert_that(result.success).is_true()
112 assert_that(result.output).contains("Installed plugins (2)")
113 assert_that(result.issues_count).is_equal_to(0)
116@patch("lintro.tools.implementations.pytest.pytest_handlers.check_plugin_installed")
117def test_handle_check_plugins_some_missing(mock_check: MagicMock) -> None:
118 """handle_check_plugins reports missing plugins.
120 Args:
121 mock_check: Mock for check_plugin_installed.
122 """
123 mock_check.side_effect = [True, False]
124 mock_tool = _make_mock_tool()
126 result = handle_check_plugins(mock_tool, "pytest-cov, pytest-missing")
128 assert_that(result.success).is_false()
129 assert_that(result.output).contains("Missing plugins (1)")
130 assert_that(result.output).contains("pytest-missing")
131 assert_that(result.issues_count).is_equal_to(1)
134def test_handle_check_plugins_no_plugins_specified() -> None:
135 """handle_check_plugins errors when no plugins specified."""
136 mock_tool = _make_mock_tool()
138 result = handle_check_plugins(mock_tool, None)
140 assert_that(result.success).is_false()
141 assert_that(result.output).contains("required_plugins must be specified")
144# =============================================================================
145# handle_collect_only tests
146# =============================================================================
149def test_handle_collect_only_success() -> None:
150 """handle_collect_only parses collected tests."""
151 mock_tool = _make_mock_tool()
152 mock_tool._run_subprocess.return_value = (
153 True,
154 "<Function test_one>\n<Function test_two>\ntest_file.py::test_three",
155 )
157 result = handle_collect_only(mock_tool, ["tests/"])
159 assert_that(result.success).is_true()
160 assert_that(result.output).contains("Collected")
161 assert_that(result.output).contains("test_one")
164def test_handle_collect_only_failure() -> None:
165 """handle_collect_only handles subprocess failure."""
166 mock_tool = _make_mock_tool()
167 mock_tool._run_subprocess.return_value = (False, "Error message")
169 result = handle_collect_only(mock_tool, ["tests/"])
171 assert_that(result.success).is_false()
172 assert_that(result.output).is_equal_to("Error message")
175def test_handle_collect_only_exception() -> None:
176 """handle_collect_only handles exceptions."""
177 mock_tool = _make_mock_tool()
178 mock_tool._run_subprocess.side_effect = OSError("Command not found")
180 result = handle_collect_only(mock_tool, ["tests/"])
182 assert_that(result.success).is_false()
183 assert_that(result.output).contains("Error collecting tests")
186# =============================================================================
187# handle_list_fixtures tests
188# =============================================================================
191def test_handle_list_fixtures_success() -> None:
192 """handle_list_fixtures returns fixture output."""
193 mock_tool = _make_mock_tool()
194 mock_tool._run_subprocess.return_value = (True, "tmp_path\ncaplog\nmonkeypatch")
196 result = handle_list_fixtures(mock_tool, ["tests/"])
198 assert_that(result.success).is_true()
199 assert_that(result.output).contains("tmp_path")
202def test_handle_list_fixtures_failure() -> None:
203 """handle_list_fixtures handles failure."""
204 mock_tool = _make_mock_tool()
205 mock_tool._run_subprocess.return_value = (False, "Error")
207 result = handle_list_fixtures(mock_tool, ["tests/"])
209 assert_that(result.success).is_false()
212def test_handle_list_fixtures_exception() -> None:
213 """handle_list_fixtures handles exceptions."""
214 mock_tool = _make_mock_tool()
215 mock_tool._run_subprocess.side_effect = ValueError("Bad value")
217 result = handle_list_fixtures(mock_tool, ["tests/"])
219 assert_that(result.success).is_false()
220 assert_that(result.output).contains("Error listing fixtures")
223# =============================================================================
224# handle_fixture_info tests
225# =============================================================================
228def test_handle_fixture_info_found() -> None:
229 """handle_fixture_info finds fixture details."""
230 mock_tool = _make_mock_tool()
231 mock_tool._run_subprocess.return_value = (
232 True,
233 "tmp_path -- Provides temporary directory\n"
234 " Scope: function\n"
235 "caplog -- Captures logging output",
236 )
238 result = handle_fixture_info(mock_tool, "tmp_path", ["tests/"])
240 assert_that(result.success).is_true()
241 assert_that(result.output).contains("tmp_path")
244def test_handle_fixture_info_not_found() -> None:
245 """handle_fixture_info reports not found."""
246 mock_tool = _make_mock_tool()
247 mock_tool._run_subprocess.return_value = (True, "other_fixture -- Some fixture")
249 result = handle_fixture_info(mock_tool, "nonexistent", ["tests/"])
251 assert_that(result.success).is_false()
252 assert_that(result.output).contains("not found")
255def test_handle_fixture_info_exception() -> None:
256 """handle_fixture_info handles exceptions."""
257 mock_tool = _make_mock_tool()
258 mock_tool._run_subprocess.side_effect = RuntimeError("Runtime error")
260 result = handle_fixture_info(mock_tool, "tmp_path", ["tests/"])
262 assert_that(result.success).is_false()
263 assert_that(result.output).contains("Error getting fixture info")
266# =============================================================================
267# handle_list_markers tests
268# =============================================================================
271def test_handle_list_markers_success() -> None:
272 """handle_list_markers returns markers output."""
273 mock_tool = _make_mock_tool()
274 mock_tool._run_subprocess.return_value = (
275 True,
276 "@pytest.mark.skip\n@pytest.mark.parametrize",
277 )
279 result = handle_list_markers(mock_tool)
281 assert_that(result.success).is_true()
282 assert_that(result.output).contains("pytest.mark")
285def test_handle_list_markers_failure() -> None:
286 """handle_list_markers handles failure."""
287 mock_tool = _make_mock_tool()
288 mock_tool._run_subprocess.return_value = (False, "Error")
290 result = handle_list_markers(mock_tool)
292 assert_that(result.success).is_false()
295def test_handle_list_markers_exception() -> None:
296 """handle_list_markers handles exceptions."""
297 mock_tool = _make_mock_tool()
298 mock_tool._run_subprocess.side_effect = OSError("Error")
300 result = handle_list_markers(mock_tool)
302 assert_that(result.success).is_false()
303 assert_that(result.output).contains("Error listing markers")
306# =============================================================================
307# handle_parametrize_help tests
308# =============================================================================
311def test_handle_parametrize_help_returns_help_text() -> None:
312 """handle_parametrize_help returns help text."""
313 mock_tool = _make_mock_tool()
315 result = handle_parametrize_help(mock_tool)
317 assert_that(result.success).is_true()
318 assert_that(result.output).contains("Parametrization Help")
319 assert_that(result.output).contains("@pytest.mark.parametrize")
320 assert_that(result.output).contains("Example:")