Coverage for tests / unit / logging / test_console_logger.py: 100%
51 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"""Unit tests for console logger output and summaries."""
3from __future__ import annotations
5from pathlib import Path
7import pytest
8from assertpy import assert_that
10from lintro.enums.action import Action
11from lintro.utils.console import ThreadSafeConsoleLogger, create_logger
14def test_create_logger_and_basic_methods(
15 tmp_path: Path,
16 capsys: pytest.CaptureFixture[str],
17) -> None:
18 """Exercise basic logging methods and ensure files are created.
20 Args:
21 tmp_path: Temporary directory for artifacts.
22 capsys: Pytest capture fixture for stdout.
23 """
24 logger = create_logger(run_dir=tmp_path, verbose=True, raw_output=False)
25 assert_that(isinstance(logger, ThreadSafeConsoleLogger)).is_true()
26 logger.info("info message")
27 logger.debug("debug message")
28 logger.warning("warn message")
29 logger.error("error message")
30 logger.print_lintro_header()
31 logger.print_tool_header(tool_name="ruff", action="check")
32 logger.print_tool_result(tool_name="ruff", output="", issues_count=0)
33 raw = (
34 "\n [*] 2 fixable\n"
35 " Formatting issues:\n"
36 " Would reformat: file1.py\n"
37 " Would reformat: file2.py\n"
38 " Found 3 issue(s) that cannot be auto-fixed\n"
39 " "
40 ).strip()
41 logger.print_tool_result(
42 tool_name="ruff",
43 output="some formatted table",
44 issues_count=3,
45 raw_output_for_meta=raw,
46 action=Action.CHECK,
47 )
49 class Result:
50 def __init__(
51 self,
52 name: str,
53 issues_count: int,
54 success: bool,
55 output: str = "",
56 ) -> None:
57 self.name = name
58 self.issues_count = issues_count
59 self.success = success
60 self.output = output
62 logger.print_execution_summary(
63 action=Action.CHECK,
64 tool_results=[Result("ruff", 1, False)],
65 )
67 class FmtResult:
68 def __init__(
69 self,
70 name: str,
71 fixed: int,
72 remaining: int,
73 success: bool = True,
74 output: str = "",
75 ) -> None:
76 self.name = name
77 self.fixed_issues_count = fixed
78 self.remaining_issues_count = remaining
79 self.success = success
80 self.output = output
82 logger.print_execution_summary(
83 action=Action.FIX,
84 tool_results=[FmtResult("ruff", fixed=2, remaining=0, success=True)],
85 )
86 logger.save_console_log()
87 assert_that((tmp_path / "console.log").exists()).is_true()
88 out = capsys.readouterr().out
89 assert_that(out).contains("LINTRO")
90 assert_that(out).contains("Running ruff (check)")
91 # Output should contain either issue-related text or pass/fail status
92 assert_that(
93 "issues" in out.lower() or "PASS" in out or "FAIL" in out,
94 ).is_true()
97def test_summary_marks_fail_on_tool_failure(
98 tmp_path: Path,
99 capsys: pytest.CaptureFixture[str],
100) -> None:
101 """Ensure summary marks FAIL when any tool result indicates failure.
103 Args:
104 tmp_path: Temporary directory for artifacts.
105 capsys: Pytest capture fixture for stdout.
106 """
107 logger = create_logger(run_dir=tmp_path, verbose=False, raw_output=False)
109 class Result:
110 def __init__(
111 self,
112 name: str,
113 issues_count: int,
114 success: bool,
115 output: str = "",
116 ) -> None:
117 self.name = name
118 self.issues_count = issues_count
119 self.success = success
120 self.output = output
122 logger.print_execution_summary(
123 action=Action.CHECK,
124 tool_results=[Result("bandit", 0, False, output="Failed to parse")],
125 )
126 out = capsys.readouterr().out
127 assert_that(out).contains("FAIL")
128 assert_that(out.split("FAIL")[0]).does_not_contain("PASS")