Переписал почти все тесты

feat: улучшено логирование и обработка скорингов в PostService и RagApiClient

- Добавлены отладочные сообщения для передачи скорингов в функции обработки постов.
- Обновлено логирование успешного получения скорингов из RAG API с дополнительной информацией.
- Оптимизирована обработка скорингов в функции get_text_message для улучшения отладки.
- Обновлены тесты для проверки новых функциональных возможностей и обработки ошибок.
This commit is contained in:
2026-01-30 00:55:47 +03:00
parent e87f4af82f
commit a5faa4bdc6
27 changed files with 4320 additions and 8 deletions

164
tests/test_decorators.py Normal file
View File

@@ -0,0 +1,164 @@
"""
Тесты для декораторов group и private handlers (error_handler).
"""
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from aiogram import types
from helper_bot.handlers.group.decorators import error_handler as group_error_handler
from helper_bot.handlers.private.decorators import (
error_handler as private_error_handler,
)
class FakeMessage:
"""Класс-маркер, чтобы мок проходил isinstance(..., types.Message) в декораторе."""
pass
@pytest.mark.unit
@pytest.mark.asyncio
class TestGroupErrorHandler:
"""Тесты для error_handler из group/decorators."""
async def test_success_returns_result(self):
"""При успешном выполнении возвращается результат функции."""
@group_error_handler
async def sample_handler():
return "ok"
result = await sample_handler()
assert result == "ok"
async def test_exception_is_reraised(self):
"""При исключении оно пробрасывается дальше."""
@group_error_handler
async def failing_handler():
raise ValueError("test error")
with pytest.raises(ValueError, match="test error"):
await failing_handler()
@patch("helper_bot.handlers.group.decorators.logger")
async def test_exception_is_logged(self, mock_logger):
"""При исключении вызывается logger.error."""
@group_error_handler
async def failing_handler():
raise RuntimeError("logged error")
with pytest.raises(RuntimeError):
await failing_handler()
mock_logger.error.assert_called_once()
assert "logged error" in mock_logger.error.call_args[0][0]
assert "failing_handler" in mock_logger.error.call_args[0][0]
@patch("helper_bot.handlers.group.decorators.types")
@patch("helper_bot.utils.base_dependency_factory.get_global_instance")
@patch("helper_bot.handlers.group.decorators.logger")
async def test_exception_sends_to_important_logs_when_message_has_bot(
self, mock_logger, mock_get_global, mock_types
):
"""При исключении и наличии message с bot отправляется сообщение в important_logs."""
mock_types.Message = FakeMessage
message = MagicMock()
message.__class__ = FakeMessage
message.bot = MagicMock()
message.bot.send_message = AsyncMock()
mock_bdf = MagicMock()
mock_bdf.settings = {"Telegram": {"important_logs": "-100123"}}
mock_get_global.return_value = mock_bdf
@group_error_handler
async def failing_handler(msg):
assert msg is message
raise ValueError("error for logs")
with pytest.raises(ValueError):
await failing_handler(message)
mock_get_global.assert_called_once()
message.bot.send_message.assert_called_once()
call_kwargs = message.bot.send_message.call_args[1]
assert call_kwargs["chat_id"] == "-100123"
call_text = call_kwargs["text"]
assert "error for logs" in call_text
assert "failing_handler" in call_text
assert "Traceback" in call_text
@pytest.mark.unit
@pytest.mark.asyncio
class TestPrivateErrorHandler:
"""Тесты для error_handler из private/decorators."""
async def test_success_returns_result(self):
"""При успешном выполнении возвращается результат функции."""
@private_error_handler
async def sample_handler():
return 42
result = await sample_handler()
assert result == 42
async def test_exception_is_reraised(self):
"""При исключении оно пробрасывается дальше."""
@private_error_handler
async def failing_handler():
raise TypeError("private error")
with pytest.raises(TypeError, match="private error"):
await failing_handler()
@patch("helper_bot.handlers.private.decorators.logger")
async def test_exception_is_logged(self, mock_logger):
"""При исключении вызывается logger.error."""
@private_error_handler
async def failing_handler():
raise KeyError("key missing")
with pytest.raises(KeyError):
await failing_handler()
mock_logger.error.assert_called_once()
assert "key missing" in mock_logger.error.call_args[0][0]
@patch("helper_bot.handlers.private.decorators.types")
@patch("helper_bot.utils.base_dependency_factory.get_global_instance")
async def test_exception_sends_to_important_logs_when_message_has_bot(
self, mock_get_global, mock_types
):
"""При исключении и наличии message с bot отправляется сообщение в important_logs."""
mock_types.Message = FakeMessage
message = MagicMock()
message.__class__ = FakeMessage
message.bot = MagicMock()
message.bot.send_message = AsyncMock()
mock_bdf = MagicMock()
mock_bdf.settings = {"Telegram": {"important_logs": "-100456"}}
mock_get_global.return_value = mock_bdf
@private_error_handler
async def failing_handler(msg):
raise RuntimeError("private runtime")
with pytest.raises(RuntimeError):
await failing_handler(message)
mock_get_global.assert_called_once()
message.bot.send_message.assert_called_once()
call_kwargs = message.bot.send_message.call_args[1]
assert call_kwargs["chat_id"] == "-100456"
call_text = call_kwargs["text"]
assert "private runtime" in call_text
assert "failing_handler" in call_text
async def test_no_message_in_args_no_send(self):
"""Если в args нет Message, send_message не вызывается (только логирование)."""
@private_error_handler
async def failing_handler():
raise ValueError("no message")
with pytest.raises(ValueError):
await failing_handler()
# get_global_instance не должен вызываться, т.к. message не найден в args