Coverage for tests / unit / tools / ruff / check / test_with_issues.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"""Tests for execute_ruff_check with issues found."""
3from __future__ import annotations
5from typing import cast
6from unittest.mock import MagicMock, patch
8from assertpy import assert_that
10from lintro.parsers.ruff.ruff_format_issue import RuffFormatIssue
11from lintro.parsers.ruff.ruff_issue import RuffIssue
12from lintro.tools.implementations.ruff.check import execute_ruff_check
15def test_execute_ruff_check_with_lint_issues_returns_failure(
16 mock_ruff_tool: MagicMock,
17) -> None:
18 """Return failure when lint issues are found.
20 Args:
21 mock_ruff_tool: Mock RuffTool instance for testing.
22 """
23 lint_issues = [
24 RuffIssue(
25 file="test.py",
26 line=1,
27 column=1,
28 code="F401",
29 message="os imported but unused",
30 fixable=True,
31 fix_applicability="safe",
32 ),
33 ]
35 with (
36 patch(
37 "lintro.tools.implementations.ruff.check.walk_files_with_excludes",
38 return_value=["test.py"],
39 ),
40 patch(
41 "lintro.tools.implementations.ruff.check.run_subprocess_with_timeout",
42 return_value=(False, '[{"code": "F401"}]'),
43 ),
44 patch(
45 "lintro.tools.implementations.ruff.check.parse_ruff_output",
46 return_value=lint_issues,
47 ),
48 ):
49 result = execute_ruff_check(mock_ruff_tool, ["/test/project"])
51 assert_that(result.success).is_false()
52 assert_that(result.issues_count).is_equal_to(1)
53 assert_that(result.issues).is_not_none()
54 assert_that(result.issues).is_length(1)
55 first_issue = cast(RuffIssue, result.issues[0]) # type: ignore[index] # validated via is_not_none
56 assert_that(first_issue.code).is_equal_to("F401")
59def test_execute_ruff_check_with_multiple_lint_issues(
60 mock_ruff_tool: MagicMock,
61) -> None:
62 """Return correct count when multiple lint issues are found.
64 Args:
65 mock_ruff_tool: Mock RuffTool instance for testing.
66 """
67 lint_issues = [
68 RuffIssue(file="test.py", line=1, column=1, code="F401", message="unused"),
69 RuffIssue(file="test.py", line=5, column=89, code="E501", message="too long"),
70 RuffIssue(file="test.py", line=10, column=1, code="W291", message="whitespace"),
71 ]
73 with (
74 patch(
75 "lintro.tools.implementations.ruff.check.walk_files_with_excludes",
76 return_value=["test.py"],
77 ),
78 patch(
79 "lintro.tools.implementations.ruff.check.run_subprocess_with_timeout",
80 return_value=(False, "[]"),
81 ),
82 patch(
83 "lintro.tools.implementations.ruff.check.parse_ruff_output",
84 return_value=lint_issues,
85 ),
86 ):
87 result = execute_ruff_check(mock_ruff_tool, ["/test/project"])
89 assert_that(result.success).is_false()
90 assert_that(result.issues_count).is_equal_to(3)
91 assert_that(result.issues).is_length(3)
94def test_execute_ruff_check_with_format_issues_returns_failure(
95 mock_ruff_tool: MagicMock,
96) -> None:
97 """Return failure when format issues are found.
99 Args:
100 mock_ruff_tool: Mock RuffTool instance for testing.
101 """
102 mock_ruff_tool.options["format_check"] = True
104 with (
105 patch(
106 "lintro.tools.implementations.ruff.check.walk_files_with_excludes",
107 return_value=["test.py"],
108 ),
109 patch(
110 "lintro.tools.implementations.ruff.check.run_subprocess_with_timeout",
111 return_value=(True, ""),
112 ),
113 patch(
114 "lintro.tools.implementations.ruff.check.parse_ruff_output",
115 return_value=[],
116 ),
117 patch(
118 "lintro.tools.implementations.ruff.check.parse_ruff_format_check_output",
119 return_value=["test.py"],
120 ),
121 ):
122 result = execute_ruff_check(mock_ruff_tool, ["/test/project"])
124 assert_that(result.success).is_false()
125 assert_that(result.issues_count).is_equal_to(1)
126 # Format issues should be RuffFormatIssue instances
127 assert_that(result.issues).is_not_none()
128 assert_that(isinstance(result.issues[0], RuffFormatIssue)).is_true() # type: ignore[index] # validated via is_not_none
131def test_execute_ruff_check_combines_lint_and_format_issues(
132 mock_ruff_tool: MagicMock,
133) -> None:
134 """Combine lint and format issues in result.
136 Args:
137 mock_ruff_tool: Mock RuffTool instance for testing.
138 """
139 mock_ruff_tool.options["format_check"] = True
140 lint_issues = [
141 RuffIssue(file="test.py", line=1, column=1, code="F401", message="unused"),
142 ]
144 with (
145 patch(
146 "lintro.tools.implementations.ruff.check.walk_files_with_excludes",
147 return_value=["test.py", "other.py"],
148 ),
149 patch(
150 "lintro.tools.implementations.ruff.check.run_subprocess_with_timeout",
151 return_value=(False, "[]"),
152 ),
153 patch(
154 "lintro.tools.implementations.ruff.check.parse_ruff_output",
155 return_value=lint_issues,
156 ),
157 patch(
158 "lintro.tools.implementations.ruff.check.parse_ruff_format_check_output",
159 return_value=["other.py"],
160 ),
161 ):
162 result = execute_ruff_check(mock_ruff_tool, ["/test/project"])
164 assert_that(result.success).is_false()
165 assert_that(result.issues_count).is_equal_to(2)
166 assert_that(result.issues).is_length(2)