Files
cpl/test/core/log/log_test.py
clu 27205022a5
Some checks failed
Test before pr merge / test-lint (pull_request) Successful in 8s
Test before pr merge / test (pull_request) Failing after 36s
test(core): extend coverage — console, errors, log, service, time, benchmark
Add missing test modules for previously untested core areas:
- console: ForegroundColorEnum, BackgroundColorEnum, Console methods
- errors: dependency_error, module_dependency_error
- log: LogLevel ordering/values, LogSettings, Logger (should_log, format, file write, fatal)
- service: HostedService, StartupTask, CronjobABC (start/stop/loop/task cancellation)
- time: TimeFormatSettings properties and setters
- utils: Benchmark.time / .memory / .all call-count and output

Also fix existing test files: environment cleanup, cron exception specificity,
json_processor kwargs bug doc, configuration_model_abc to_dict bug doc.
All 199 tests pass, black clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 19:34:52 +02:00

153 lines
4.6 KiB
Python

import os
import pytest
from cpl.core.log.log_level import LogLevel
from cpl.core.log.log_settings import LogSettings
from cpl.core.log.logger import Logger
from cpl.core.log.logger_abc import LoggerABC
# --- LogLevel ---
def test_log_level_values():
assert LogLevel.off.value == "OFF"
assert LogLevel.trace.value == "TRC"
assert LogLevel.debug.value == "DEB"
assert LogLevel.info.value == "INF"
assert LogLevel.warning.value == "WAR"
assert LogLevel.error.value == "ERR"
assert LogLevel.fatal.value == "FAT"
def test_log_level_order():
levels = list(LogLevel)
assert levels.index(LogLevel.trace) < levels.index(LogLevel.debug)
assert levels.index(LogLevel.debug) < levels.index(LogLevel.info)
assert levels.index(LogLevel.info) < levels.index(LogLevel.warning)
assert levels.index(LogLevel.warning) < levels.index(LogLevel.error)
assert levels.index(LogLevel.error) < levels.index(LogLevel.fatal)
def test_log_level_by_name():
assert LogLevel["info"] == LogLevel.info
assert LogLevel["error"] == LogLevel.error
# --- LogSettings ---
def test_log_settings_defaults():
s = LogSettings()
assert s.path == "logs"
assert s.filename == "app.log"
assert s.console == LogLevel.info
assert s.level == LogLevel.info
def test_log_settings_from_src():
s = LogSettings({"path": "custom_logs", "filename": "myapp.log"})
assert s.path == "custom_logs"
assert s.filename == "myapp.log"
# --- LoggerABC ---
def test_logger_abc_cannot_instantiate():
with pytest.raises(TypeError):
LoggerABC()
# --- Logger ---
def test_logger_creates_instance(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
logger = Logger(__name__)
assert logger is not None
def test_logger_log_file_property(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
logger = Logger(__name__)
assert logger.log_file.startswith("logs/")
assert logger.log_file.endswith(".log")
def test_logger_should_log_same_level(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
logger = Logger(__name__)
assert logger._should_log(LogLevel.info, LogLevel.info) is True
assert logger._should_log(LogLevel.error, LogLevel.error) is True
def test_logger_should_log_higher_level(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
logger = Logger(__name__)
assert logger._should_log(LogLevel.error, LogLevel.info) is True
assert logger._should_log(LogLevel.fatal, LogLevel.debug) is True
def test_logger_should_not_log_lower_level(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
logger = Logger(__name__)
assert logger._should_log(LogLevel.debug, LogLevel.info) is False
assert logger._should_log(LogLevel.trace, LogLevel.warning) is False
def test_logger_file_format_message(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
logger = Logger("test_src")
msg = logger._file_format_message("INF", "2024-01-01 00:00:00.000000", "hello", "world")
assert "INF" in msg
assert "hello" in msg
assert "world" in msg
assert "test_src" in msg
def test_logger_console_format_message(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
logger = Logger("test_src")
msg = logger._console_format_message("DEB", "2024-01-01 00:00:00.000000", "debug message")
assert "DEB" in msg
assert "debug message" in msg
def test_logger_info_writes_file(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
logger = Logger(__name__)
logger.info("test info message")
log_files = list(tmp_path.glob("logs/*.log"))
assert len(log_files) > 0
content = log_files[0].read_text()
assert "test info message" in content
def test_logger_debug_below_info_not_written_to_file(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
# Default level is INFO, so DEBUG should not appear in the file
logger = Logger(__name__)
logger.debug("should not appear in file")
log_files = list(tmp_path.glob("logs/*.log"))
if log_files:
content = log_files[0].read_text()
assert "should not appear in file" not in content
def test_logger_set_level_invalid(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
with pytest.raises(ValueError):
Logger.set_level("INVALID_LEVEL")
def test_logger_fatal_exits(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
logger = Logger(__name__)
with pytest.raises(SystemExit):
logger.fatal("fatal error")
def test_logger_fatal_prevent_quit(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
logger = Logger(__name__)
logger.fatal("fatal no quit", prevent_quit=True) # Should not raise