Some checks failed
Build and Push Docker Image / build-and-push (push) Has been cancelled
181 lines
7.6 KiB
Python
181 lines
7.6 KiB
Python
"""
|
|
Tests for logger module.
|
|
"""
|
|
import os
|
|
import logging
|
|
import tempfile
|
|
import pytest
|
|
from unittest.mock import patch, Mock
|
|
|
|
import sys
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))
|
|
|
|
from src.logger import init_logger
|
|
|
|
|
|
class TestLogger:
|
|
"""Test cases for the logger module."""
|
|
|
|
def test_init_logger_basic(self, temp_log_dir):
|
|
"""Test basic logger initialization."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger = init_logger("test_logger", testing_mode=False)
|
|
|
|
assert isinstance(logger, logging.Logger)
|
|
assert logger.name == "test_logger"
|
|
assert logger.level == logging.INFO
|
|
|
|
def test_init_logger_testing_mode(self, temp_log_dir):
|
|
"""Test logger initialization in testing mode."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger = init_logger("test_logger", testing_mode=True)
|
|
|
|
assert logger.level == logging.DEBUG
|
|
|
|
def test_init_logger_production_mode(self, temp_log_dir):
|
|
"""Test logger initialization in production mode."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger = init_logger("test_logger", testing_mode=False)
|
|
|
|
assert logger.level == logging.INFO
|
|
|
|
def test_file_handlers_created(self, temp_log_dir):
|
|
"""Test that file handlers are created correctly."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger = init_logger("test_logger", testing_mode=False)
|
|
|
|
# Check that handlers were added
|
|
assert len(logger.handlers) >= 3 # At least 3 file handlers
|
|
|
|
def test_file_handler_levels(self, temp_log_dir):
|
|
"""Test that file handlers have correct log levels."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger = init_logger("test_logger", testing_mode=False)
|
|
|
|
handler_levels = [handler.level for handler in logger.handlers if isinstance(handler, logging.FileHandler)]
|
|
|
|
# Should have handlers for DEBUG, WARNING, and ERROR levels
|
|
assert logging.DEBUG in handler_levels
|
|
assert logging.WARNING in handler_levels
|
|
assert logging.ERROR in handler_levels
|
|
|
|
def test_log_file_paths(self, temp_log_dir):
|
|
"""Test that log files are created with correct paths."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger = init_logger("test_logger", testing_mode=False)
|
|
|
|
# Log something to trigger file creation
|
|
logger.debug("Test debug message")
|
|
logger.warning("Test warning message")
|
|
logger.error("Test error message")
|
|
|
|
# Check that log files would be created (paths are correct)
|
|
expected_files = [
|
|
os.path.join(temp_log_dir, "app.log"),
|
|
os.path.join(temp_log_dir, "app.warning.log"),
|
|
os.path.join(temp_log_dir, "app.error.log")
|
|
]
|
|
|
|
# The files should exist or be ready to be created
|
|
for handler in logger.handlers:
|
|
if isinstance(handler, logging.FileHandler):
|
|
assert handler.baseFilename in expected_files
|
|
|
|
def test_formatter_format(self, temp_log_dir):
|
|
"""Test that formatters are set correctly."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger = init_logger("test_logger", testing_mode=False)
|
|
|
|
expected_format = "%(asctime)s - %(name)s - %(funcName)s - %(levelname)s - %(message)s"
|
|
|
|
for handler in logger.handlers:
|
|
if isinstance(handler, logging.FileHandler):
|
|
assert handler.formatter._fmt == expected_format
|
|
|
|
@patch('colorlog.basicConfig')
|
|
def test_colorlog_configuration(self, mock_basicConfig, temp_log_dir):
|
|
"""Test that colorlog is configured correctly."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
init_logger("test_logger", testing_mode=False)
|
|
|
|
mock_basicConfig.assert_called_once()
|
|
|
|
# Check that format includes color and bold formatting
|
|
call_args = mock_basicConfig.call_args
|
|
assert 'format' in call_args[1]
|
|
format_string = call_args[1]['format']
|
|
assert '%(log_color)s' in format_string
|
|
assert '\033[1m' in format_string # Bold sequence
|
|
|
|
def test_multiple_logger_instances(self, temp_log_dir):
|
|
"""Test creating multiple logger instances."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger1 = init_logger("logger1", testing_mode=False)
|
|
logger2 = init_logger("logger2", testing_mode=True)
|
|
|
|
assert logger1.name == "logger1"
|
|
assert logger2.name == "logger2"
|
|
assert logger1.level == logging.INFO
|
|
assert logger2.level == logging.DEBUG
|
|
|
|
def test_logger_inheritance(self, temp_log_dir):
|
|
"""Test that logger follows Python logging hierarchy."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger = init_logger("test.module.logger", testing_mode=False)
|
|
|
|
assert logger.name == "test.module.logger"
|
|
|
|
@patch('logging.FileHandler')
|
|
def test_file_handler_error_handling(self, mock_file_handler, temp_log_dir):
|
|
"""Test error handling when file handler creation fails."""
|
|
mock_file_handler.side_effect = PermissionError("Cannot create log file")
|
|
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
# Should not raise an exception, but handle gracefully
|
|
try:
|
|
logger = init_logger("test_logger", testing_mode=False)
|
|
# Logger should still be created, just without file handlers
|
|
assert isinstance(logger, logging.Logger)
|
|
except PermissionError:
|
|
pytest.fail("init_logger should handle file creation errors gracefully")
|
|
|
|
def test_logger_name_parameter(self, temp_log_dir):
|
|
"""Test that logger name is set correctly from parameter."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
test_name = "my.custom.logger.name"
|
|
logger = init_logger(test_name, testing_mode=False)
|
|
|
|
assert logger.name == test_name
|
|
|
|
def test_testing_mode_boolean(self, temp_log_dir):
|
|
"""Test that testing_mode parameter accepts boolean values."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger_true = init_logger("test1", testing_mode=True)
|
|
logger_false = init_logger("test2", testing_mode=False)
|
|
|
|
assert logger_true.level == logging.DEBUG
|
|
assert logger_false.level == logging.INFO
|
|
|
|
def test_log_format_contains_required_fields(self, temp_log_dir):
|
|
"""Test that log format contains all required fields."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger = init_logger("test_logger", testing_mode=False)
|
|
|
|
log_format = "%(asctime)s - %(name)s - %(funcName)s - %(levelname)s - %(message)s"
|
|
|
|
# Check that format contains all expected fields
|
|
expected_fields = ['%(asctime)s', '%(name)s', '%(funcName)s', '%(levelname)s', '%(message)s']
|
|
for field in expected_fields:
|
|
assert field in log_format
|
|
|
|
def test_handler_file_mode(self, temp_log_dir):
|
|
"""Test that file handlers use append mode by default."""
|
|
with patch('logger.LOG_PATH', temp_log_dir):
|
|
logger = init_logger("test_logger", testing_mode=False)
|
|
|
|
# File handlers should be in append mode by default
|
|
for handler in logger.handlers:
|
|
if isinstance(handler, logging.FileHandler):
|
|
# FileHandler uses 'a' mode by default
|
|
assert hasattr(handler, 'mode') # Basic check that it's a file handler
|