discordBot/tests/test_logger.py

147 lines
4.7 KiB
Python

"""Тесты для utils/logger.py — проверка настройки логирования."""
import logging
import os
import tempfile
from pathlib import Path
from utils.logger import setup_logging
def test_console_handler_added() -> None:
"""setup_logging добавляет StreamHandler на stdout."""
with _isolated_logger() as root:
handlers = [h for h in root.handlers if isinstance(h, logging.StreamHandler)]
assert len(handlers) >= 1
def test_default_level_is_info() -> None:
"""Уровень по умолчанию — INFO."""
with _isolated_logger() as root:
assert root.level == logging.INFO
def test_custom_level_from_env() -> None:
"""LOG_LEVEL из окружения влияет на уровень."""
os.environ["LOG_LEVEL"] = "DEBUG"
try:
with _isolated_logger() as root:
assert root.level == logging.DEBUG
finally:
os.environ.pop("LOG_LEVEL", None)
def test_invalid_level_defaults_to_info() -> None:
"""Неизвестный LOG_LEVEL fallback на INFO."""
os.environ["LOG_LEVEL"] = "NOTAREALLEVEL"
try:
with _isolated_logger() as root:
assert root.level == logging.INFO
finally:
os.environ.pop("LOG_LEVEL", None)
def test_file_handler_when_logs_dir_exists() -> None:
"""RotatingFileHandler добавляется если директория logs существует."""
import logging.handlers
orig_cwd = os.getcwd()
with tempfile.TemporaryDirectory() as tmpdir:
logs_dir = Path(tmpdir) / "logs"
logs_dir.mkdir()
os.chdir(logs_dir.parent)
try:
with _isolated_logger() as root:
file_handlers = [
h
for h in root.handlers
if isinstance(h, logging.handlers.RotatingFileHandler)
]
assert len(file_handlers) >= 1
# Закрыть file handler чтобы освободить файл на Windows
for h in file_handlers:
h.close()
finally:
os.chdir(orig_cwd)
def test_logs_dir_created_automatically() -> None:
"""Директория logs создаётся автоматически, если её нет."""
import logging.handlers
orig_cwd = os.getcwd()
with tempfile.TemporaryDirectory() as tmpdir:
os.chdir(tmpdir)
# Убедиться что logs/ нет
logs_dir = Path("logs")
assert not logs_dir.exists()
try:
with _isolated_logger() as root:
assert logs_dir.exists()
file_handlers = [
h
for h in root.handlers
if isinstance(h, logging.handlers.RotatingFileHandler)
]
assert len(file_handlers) >= 1
# Закрыть file handler чтобы освободить файл на Windows
for h in file_handlers:
h.close()
finally:
os.chdir(orig_cwd)
def test_aiohttp_suppressed() -> None:
"""Логгер aiohttp подавлен до WARNING."""
with _isolated_logger():
aiohttp_logger = logging.getLogger("aiohttp")
assert aiohttp_logger.level == logging.WARNING
def test_discord_level_is_info() -> None:
"""Логгер discord установлен на INFO."""
with _isolated_logger():
discord_logger = logging.getLogger("discord")
assert discord_logger.level == logging.INFO
def test_log_message_format() -> None:
"""Формат сообщения: время, уровень, имя модуля, текст."""
import io
import sys
with _isolated_logger() as root:
# Replace stdout with our buffer
buffer = io.StringIO()
for handler in root.handlers:
if isinstance(handler, logging.StreamHandler):
handler.stream = buffer
test_logger = logging.getLogger("test_module")
test_logger.info("test message")
output = buffer.getvalue()
assert "INFO" in output
assert "test_module" in output
assert "test message" in output
import contextlib
@contextlib.contextmanager
def _isolated_logger():
"""Создать изолированный root-логгер без handlers из других тестов."""
old_handlers = logging.getLogger().handlers[:]
old_level = logging.getLogger().level
logging.getLogger().handlers.clear()
yield setup_logging()
# Restore
logging.getLogger().handlers.clear()
logging.getLogger().handlers.extend(old_handlers)
logging.getLogger().setLevel(old_level)