Coverage for tests / unit / tools / ruff / check / test_output_truncation.py: 100%
32 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 output logging in execute_ruff_check."""
3from __future__ import annotations
5from unittest.mock import MagicMock, patch
7from assertpy import assert_that
9from lintro.tools.implementations.ruff.check import execute_ruff_check
12def test_check_failure_logs_output_to_debug_only(
13 mock_ruff_tool: MagicMock,
14) -> None:
15 """Verify check output is logged to debug only, not warning.
17 When ruff check fails (exit code non-zero due to issues found),
18 the raw JSON output should only be logged at debug level since
19 it is already parsed and displayed as a formatted table.
21 Args:
22 mock_ruff_tool: Mock RuffTool instance for testing.
23 """
24 # Create output longer than 2000 chars
25 long_output = "x" * 3000
27 with (
28 patch(
29 "lintro.tools.implementations.ruff.check.walk_files_with_excludes",
30 return_value=["test.py"],
31 ),
32 patch(
33 "lintro.tools.implementations.ruff.check.run_subprocess_with_timeout",
34 return_value=(False, long_output),
35 ),
36 patch(
37 "lintro.tools.implementations.ruff.check.parse_ruff_output",
38 return_value=[],
39 ),
40 patch("lintro.tools.implementations.ruff.check.logger") as mock_logger,
41 ):
42 execute_ruff_check(mock_ruff_tool, ["/test/project"])
44 # Verify full output was logged to debug
45 debug_calls = [str(call) for call in mock_logger.debug.call_args_list]
46 full_output_logged = any("check full output" in call for call in debug_calls)
47 assert_that(full_output_logged).described_as(
48 f"Expected full output in debug calls: {debug_calls}",
49 ).is_true()
51 # Verify no truncation warning was logged (raw JSON should not appear in console)
52 warning_calls = [str(call) for call in mock_logger.warning.call_args_list]
53 truncation_warning = any(
54 "check failed with output" in call for call in warning_calls
55 )
56 assert_that(truncation_warning).described_as(
57 f"Did not expect 'check failed with output' warning: {warning_calls}",
58 ).is_false()
61def test_format_check_failure_logs_output_to_debug_only(
62 mock_ruff_tool: MagicMock,
63) -> None:
64 """Verify format check output is logged to debug only, not warning.
66 When ruff format --check fails (exit code non-zero due to formatting issues),
67 the output should only be logged at debug level since it is already
68 parsed and displayed as a formatted table.
70 Args:
71 mock_ruff_tool: Mock RuffTool instance for testing.
72 """
73 mock_ruff_tool.options["format_check"] = True
75 # Create output longer than 2000 chars
76 long_format_output = "Would reformat: " + "x" * 3000
78 with (
79 patch(
80 "lintro.tools.implementations.ruff.check.walk_files_with_excludes",
81 return_value=["test.py"],
82 ),
83 patch(
84 "lintro.tools.implementations.ruff.check.run_subprocess_with_timeout",
85 ) as mock_subprocess,
86 patch(
87 "lintro.tools.implementations.ruff.check.parse_ruff_output",
88 return_value=[],
89 ),
90 patch(
91 "lintro.tools.implementations.ruff.check.parse_ruff_format_check_output",
92 return_value=[],
93 ),
94 patch("lintro.tools.implementations.ruff.check.logger") as mock_logger,
95 ):
96 # First call succeeds (lint), second call fails (format)
97 mock_subprocess.side_effect = [
98 (True, "[]"),
99 (False, long_format_output),
100 ]
102 execute_ruff_check(mock_ruff_tool, ["/test/project"])
104 # Verify full output was logged to debug
105 debug_calls = [str(call) for call in mock_logger.debug.call_args_list]
106 full_output_logged = any(
107 "format check full output" in call for call in debug_calls
108 )
109 assert_that(full_output_logged).described_as(
110 f"Expected full output in debug calls: {debug_calls}",
111 ).is_true()
113 # Verify no truncation warning was logged
114 warning_calls = [str(call) for call in mock_logger.warning.call_args_list]
115 truncation_warning = any(
116 "format check failed with output" in call for call in warning_calls
117 )
118 assert_that(truncation_warning).described_as(
119 f"Did not expect 'format check failed with output' warning: {warning_calls}",
120 ).is_false()
123def test_check_success_does_not_log_output(
124 mock_ruff_tool: MagicMock,
125) -> None:
126 """Verify successful check does not log output unnecessarily.
128 When ruff check succeeds (no issues), there should be no output
129 logged to debug since there's nothing to report.
131 Args:
132 mock_ruff_tool: Mock RuffTool instance for testing.
133 """
134 with (
135 patch(
136 "lintro.tools.implementations.ruff.check.walk_files_with_excludes",
137 return_value=["test.py"],
138 ),
139 patch(
140 "lintro.tools.implementations.ruff.check.run_subprocess_with_timeout",
141 return_value=(True, "[]"),
142 ),
143 patch(
144 "lintro.tools.implementations.ruff.check.parse_ruff_output",
145 return_value=[],
146 ),
147 patch("lintro.tools.implementations.ruff.check.logger") as mock_logger,
148 ):
149 execute_ruff_check(mock_ruff_tool, ["/test/project"])
151 # Verify no "check full output" logged when success
152 debug_calls = [str(call) for call in mock_logger.debug.call_args_list]
153 full_output_logged = any("check full output" in call for call in debug_calls)
154 assert_that(full_output_logged).described_as(
155 f"Did not expect 'check full output' on success: {debug_calls}",
156 ).is_false()