"""Tests for DebugLogger (backend/managers/debug_logger.py). DebugLogger is a classmethod-based utility. Its _error_log class variable persists across tests, so every test that modifies it must call DebugLogger.clear_errors() in teardown (handled by the autouse fixture). """ import sys from pathlib import Path import pytest sys.path.insert(0, str(Path(__file__).parent.parent)) from backend.managers.debug_logger import DebugLogger # ── Fixtures ────────────────────────────────────────────────────────────────── @pytest.fixture(autouse=True) def clear_error_log(): """Reset the shared _error_log class variable before and after each test.""" DebugLogger.clear_errors() yield DebugLogger.clear_errors() # ── log_error() ─────────────────────────────────────────────────────────────── class TestLogError: """Tests for log_error(): appends the message to the in-memory error list.""" def test_log_error_appends_to_error_log(self): DebugLogger.log_error("something broke") assert "something broke" in DebugLogger.get_errors() def test_log_error_multiple_messages_all_stored(self): DebugLogger.log_error("first error") DebugLogger.log_error("second error") errors = DebugLogger.get_errors() assert "first error" in errors assert "second error" in errors def test_log_error_preserves_order(self): DebugLogger.log_error("alpha") DebugLogger.log_error("beta") errors = DebugLogger.get_errors() assert errors.index("alpha") < errors.index("beta") # ── get_errors() ────────────────────────────────────────────────────────────── class TestGetErrors: """Tests for get_errors(): returns the current in-memory error list.""" def test_get_errors_empty_initially(self): assert DebugLogger.get_errors() == [] def test_get_errors_reflects_logged_errors(self): DebugLogger.log_error("boom") assert len(DebugLogger.get_errors()) == 1 # ── clear_errors() ──────────────────────────────────────────────────────────── class TestClearErrors: """Tests for clear_errors(): wipes the in-memory error list.""" def test_clear_errors_empties_list(self): DebugLogger.log_error("will be cleared") DebugLogger.clear_errors() assert DebugLogger.get_errors() == [] def test_clear_errors_on_empty_list_does_not_raise(self): DebugLogger.clear_errors() # already empty from autouse fixture # ── format_debug_output() ───────────────────────────────────────────────────── class TestFormatDebugOutput: """Tests for format_debug_output(): renders return_code, stdout, and stderr.""" def test_contains_execution_result_header(self): result = DebugLogger.format_debug_output({"return_code": 0, "stdout": "", "stderr": ""}) assert "=== Execution Result ===" in result def test_exit_code_zero_appears_in_output(self): result = DebugLogger.format_debug_output({"return_code": 0, "stdout": "", "stderr": ""}) assert "Exit Code: 0" in result def test_nonzero_exit_code_appears_in_output(self): result = DebugLogger.format_debug_output({"return_code": 1, "stdout": "", "stderr": ""}) assert "Exit Code: 1" in result def test_stdout_included_when_present(self): result = DebugLogger.format_debug_output({"return_code": 0, "stdout": "Hello", "stderr": ""}) assert "Hello" in result def test_stderr_included_when_present(self): result = DebugLogger.format_debug_output({"return_code": 1, "stdout": "", "stderr": "NameError"}) assert "NameError" in result def test_empty_stdout_shows_none_placeholder(self): result = DebugLogger.format_debug_output({"return_code": 0, "stdout": "", "stderr": ""}) assert "(none)" in result def test_missing_keys_do_not_raise(self): # format_debug_output uses .get() so absent keys fall back to defaults. result = DebugLogger.format_debug_output({}) assert isinstance(result, str)