Coverage for tests / integration / test_mypy_integration.py: 98%
54 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"""Integration tests for Mypy tool."""
3from __future__ import annotations
5import contextlib
6import os
7import shutil
8import tempfile
9from collections.abc import Iterator
10from pathlib import Path
11from typing import TYPE_CHECKING
13import pytest
14from assertpy import assert_that
16from lintro.plugins import ToolRegistry
18if TYPE_CHECKING:
19 from lintro.plugins.base import BaseToolPlugin
22@pytest.fixture(autouse=True)
23def set_lintro_test_mode_env(lintro_test_mode: object) -> Iterator[None]:
24 """Disable config injection for predictable CLI args in tests.
26 Args:
27 lintro_test_mode: Pytest fixture that enables lintro test mode.
29 Yields:
30 None: Allows the test to run with modified environment.
31 """
32 yield
35@pytest.fixture
36def mypy_tool() -> BaseToolPlugin:
37 """Create a mypy tool plugin instance for testing.
39 Returns:
40 BaseToolPlugin: Configured tool plugin instance for assertions.
41 """
42 tool = ToolRegistry.get("mypy")
43 assert tool is not None, "mypy tool not found in registry"
44 return tool
47@pytest.fixture
48def mypy_violation_file() -> Iterator[str]:
49 """Copy the mypy_violations.py sample to a temp directory for testing.
51 Yields:
52 str: Path to the temporary file containing known mypy violations.
53 """
54 repo_root = Path(__file__).resolve().parent.parent.parent
55 src = (
56 repo_root / "test_samples" / "tools" / "python" / "mypy" / "mypy_violations.py"
57 )
58 if not src.exists():
59 pytest.skip(f"Sample file {src} does not exist")
60 with tempfile.TemporaryDirectory() as tmpdir:
61 dst = os.path.join(tmpdir, "mypy_violations.py")
62 shutil.copy(src, dst)
63 yield dst
66@pytest.fixture
67def mypy_clean_file() -> Iterator[str]:
68 """Create a temporary clean Python file for mypy.
70 Yields:
71 str: Path to a temporary Python file without mypy violations.
72 """
73 content = (
74 "from typing import Annotated\n\n"
75 "def add(a: int, b: int) -> int:\n"
76 " return a + b\n"
77 )
78 with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
79 f.write(content)
80 file_path = f.name
81 try:
82 yield file_path
83 finally:
84 with contextlib.suppress(FileNotFoundError):
85 os.unlink(file_path)
88def test_mypy_tool_available(mypy_tool: BaseToolPlugin) -> None:
89 """Test that mypy tool is registered and available.
91 Args:
92 mypy_tool: Pytest fixture providing the mypy tool instance.
93 """
94 assert_that(mypy_tool).is_not_none()
95 assert_that(mypy_tool.definition.name).is_equal_to("mypy")
98def test_mypy_check_finds_violations(
99 mypy_tool: BaseToolPlugin,
100 mypy_violation_file: str,
101) -> None:
102 """Test that mypy check finds type errors in violation file.
104 Args:
105 mypy_tool: Pytest fixture providing the mypy tool instance.
106 mypy_violation_file: Pytest fixture providing file with type errors.
107 """
108 result = mypy_tool.check([mypy_violation_file], {})
110 assert_that(result).is_not_none()
111 # Mypy should find type errors in the violations file
112 assert_that(
113 result.success is False
114 or (result.issues is not None and len(result.issues) > 0),
115 ).is_true()
118def test_mypy_check_clean_file(
119 mypy_tool: BaseToolPlugin,
120 mypy_clean_file: str,
121) -> None:
122 """Test that mypy check passes on clean file.
124 Args:
125 mypy_tool: Pytest fixture providing the mypy tool instance.
126 mypy_clean_file: Pytest fixture providing path to clean file.
127 """
128 result = mypy_tool.check([mypy_clean_file], {})
130 assert_that(result).is_not_none()
131 assert_that(result.success).is_true()
132 assert_that(result.issues is None or len(result.issues) == 0).is_true()
135def test_mypy_handles_empty_path_list(mypy_tool: BaseToolPlugin) -> None:
136 """Test that mypy handles empty path list gracefully.
138 Args:
139 mypy_tool: Pytest fixture providing the mypy tool instance.
140 """
141 result = mypy_tool.check([], {})
143 # Should complete without crashing
144 assert_that(result).is_not_none()