import logging
import uuid
import pytest
from ms_service_metric.utils.logger import get_logger, get_log_level, setup_logging
@pytest.fixture
def isolated_ms_metric_logger_name():
"""Yield a unique logger short name and tear down handlers after the test.
Ensures ``get_logger`` runs its ``setup_logging`` path on a fresh logger and
that StreamHandlers are closed so they do not leak across tests.
"""
name = f"ut_iso_{uuid.uuid4().hex[:16]}"
yield name
logger = logging.getLogger(f"ms_service_metric.{name}")
for handler in list(logger.handlers):
logger.removeHandler(handler)
handler.close()
logger.setLevel(logging.NOTSET)
class TestGetLoggerGivenValidName:
def test_when_get_logger_with_name_then_return_logger(self):
logger = get_logger("test_logger")
assert isinstance(logger, logging.Logger)
assert logger.name == "ms_service_metric.test_logger"
def test_when_get_logger_multiple_times_then_return_same_logger(self):
logger1 = get_logger("test_logger")
logger2 = get_logger("test_logger")
assert logger1 is logger2
def test_when_get_logger_with_empty_name_then_return_root_logger(self):
logger = get_logger("")
assert isinstance(logger, logging.Logger)
assert logger.name == "ms_service_metric."
def test_when_get_logger_multiple_times_then_handlers_not_duplicated(
self, isolated_ms_metric_logger_name
):
"""Calling get_logger twice must not append extra handlers on the same logger."""
logger_name = isolated_ms_metric_logger_name
logger1 = get_logger(logger_name)
handler_count_first = len(logger1.handlers)
assert handler_count_first > 0
logger2 = get_logger(logger_name)
handler_count_second = len(logger2.handlers)
assert handler_count_first == handler_count_second
assert logger1 is logger2
class TestGetLogLevelGivenEnvironmentVariable:
def test_when_env_set_to_debug_then_return_debug_level(self, monkeypatch):
monkeypatch.setenv("PROF_LOG_LEVEL", "DEBUG")
assert get_log_level() == logging.DEBUG
def test_when_env_set_to_info_then_return_info_level(self, monkeypatch):
monkeypatch.setenv("PROF_LOG_LEVEL", "INFO")
assert get_log_level() == logging.INFO
def test_when_env_set_to_warning_then_return_warning_level(self, monkeypatch):
monkeypatch.setenv("PROF_LOG_LEVEL", "WARNING")
assert get_log_level() == logging.WARNING
def test_when_env_set_to_error_then_return_error_level(self, monkeypatch):
monkeypatch.setenv("PROF_LOG_LEVEL", "ERROR")
assert get_log_level() == logging.ERROR
def test_when_env_not_set_then_return_default_info_level(self, monkeypatch):
monkeypatch.delenv("PROF_LOG_LEVEL", raising=False)
assert get_log_level() == logging.INFO
def test_when_env_set_to_invalid_value_then_return_default_info_level(self, monkeypatch):
monkeypatch.setenv("PROF_LOG_LEVEL", "INVALID")
assert get_log_level() == logging.INFO
class TestSetupLoggingGivenValidLogger:
def test_when_setup_logging_then_handlers_are_configured(self):
logger = logging.getLogger("test_setup_logging")
setup_logging(logger)
assert len(logger.handlers) > 0
assert logger.level is not None
def test_when_setup_logging_with_custom_level_then_level_is_set(self):
logger = logging.getLogger("test_setup_logging_level")
setup_logging(logger, level=logging.DEBUG)
assert logger.level == logging.DEBUG
class TestLoggerFunctionality:
def test_when_log_debug_message_then_no_error_raised(self):
logger = get_logger("test_debug")
logger.setLevel(logging.DEBUG)
for handler in logger.handlers:
handler.setLevel(logging.DEBUG)
logger.debug("test debug message")
assert True
def test_when_log_info_message_then_no_error_raised(self):
logger = get_logger("test_info")
logger.info("test info message")
assert True
def test_when_log_warning_message_then_no_error_raised(self):
logger = get_logger("test_warning")
logger.warning("test warning message")
assert True
def test_when_log_error_message_then_no_error_raised(self):
logger = get_logger("test_error")
logger.error("test error message")
assert True
def test_when_log_exception_with_exc_info_then_no_error_raised(self):
logger = get_logger("test_exception")
try:
raise ValueError("test exception")
except ValueError:
logger.exception("test exception message")
assert True