Files
trends-scraper/tests/test_logger.py
2025-09-11 17:46:14 +03:00

165 lines
5.6 KiB
Python

"""
Unit tests for the Logger module.
"""
import pytest
import sys
import tempfile
import os
from pathlib import Path
from unittest.mock import patch, MagicMock
from loguru import logger
from src.logger import setup_logger, get_logger, LoggerMixin
class TestLoggerSetup:
"""Test cases for logger setup functionality."""
def test_setup_logger_default(self):
"""Test logger setup with default parameters."""
with patch('loguru.logger.remove') as mock_remove, \
patch('loguru.logger.add') as mock_add:
setup_logger()
# Verify default logger was removed
mock_remove.assert_called_once()
# Verify console logger was added
assert mock_add.call_count == 1
console_call = mock_add.call_args_list[0]
assert console_call[0][0] == sys.stderr
assert "level" in console_call[1]
assert console_call[1]["colorize"] is True
def test_setup_logger_with_file(self):
"""Test logger setup with file output."""
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
log_file = tmp_file.name
try:
with patch('loguru.logger.remove') as mock_remove, \
patch('loguru.logger.add') as mock_add:
setup_logger(log_file=log_file)
# Verify both console and file loggers were added
assert mock_add.call_count == 2
# Check file logger call
file_call = mock_add.call_args_list[1]
assert file_call[0][0] == log_file
assert "rotation" in file_call[1]
assert "retention" in file_call[1]
assert "compression" in file_call[1]
finally:
# Clean up
if os.path.exists(log_file):
os.unlink(log_file)
def test_setup_logger_verbose(self):
"""Test logger setup with verbose mode."""
with patch('loguru.logger.remove') as mock_remove, \
patch('loguru.logger.add') as mock_add:
setup_logger(verbose=True)
# Verify DEBUG level was set
console_call = mock_add.call_args_list[0]
assert console_call[1]["level"] == "DEBUG"
def test_setup_logger_custom_level(self):
"""Test logger setup with custom log level."""
with patch('loguru.logger.remove') as mock_remove, \
patch('loguru.logger.add') as mock_add:
setup_logger(log_level="WARNING")
# Verify WARNING level was set
console_call = mock_add.call_args_list[0]
assert console_call[1]["level"] == "WARNING"
def test_setup_logger_custom_rotation(self):
"""Test logger setup with custom rotation settings."""
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
log_file = tmp_file.name
try:
with patch('loguru.logger.remove') as mock_remove, \
patch('loguru.logger.add') as mock_add:
setup_logger(log_file=log_file, rotation="100 MB")
# Verify custom rotation was set
file_call = mock_add.call_args_list[1]
assert file_call[1]["rotation"] == "100 MB"
finally:
# Clean up
if os.path.exists(log_file):
os.unlink(log_file)
def test_setup_logger_exception_handler(self):
"""Test that exception handler is set up."""
with patch('loguru.logger.remove') as mock_remove, \
patch('loguru.logger.add') as mock_add, \
patch('sys.excepthook') as mock_excepthook:
setup_logger()
# Verify exception handler was set
assert mock_excepthook is not None
assert callable(mock_excepthook)
class TestGetLogger:
"""Test cases for get_logger function."""
def test_get_logger_no_name(self):
"""Test getting logger without name."""
with patch('loguru.logger.bind') as mock_bind:
get_logger()
mock_bind.assert_called_once()
def test_get_logger_with_name(self):
"""Test getting logger with name."""
with patch('loguru.logger.bind') as mock_bind:
get_logger("test_module")
mock_bind.assert_called_once_with(name="test_module")
class TestLoggerMixin:
"""Test cases for LoggerMixin class."""
def test_logger_property(self):
"""Test logger property in mixin."""
class TestClass(LoggerMixin):
pass
with patch('loguru.logger.bind') as mock_bind:
test_obj = TestClass()
_ = test_obj.logger
# Verify logger was bound with class name and object id
mock_bind.assert_called_once()
args, kwargs = mock_bind.call_args
assert kwargs["name"] == "TestClass"
assert "id" in kwargs
def test_logger_mixin_inheritance(self):
"""Test that logger mixin works with inheritance."""
class ParentClass(LoggerMixin):
pass
class ChildClass(ParentClass):
pass
with patch('loguru.logger.bind') as mock_bind:
child_obj = ChildClass()
_ = child_obj.logger
# Verify logger was bound with child class name
args, kwargs = mock_bind.call_args
assert kwargs["name"] == "ChildClass"