Переписал почти все тесты
feat: улучшено логирование и обработка скорингов в PostService и RagApiClient - Добавлены отладочные сообщения для передачи скорингов в функции обработки постов. - Обновлено логирование успешного получения скорингов из RAG API с дополнительной информацией. - Оптимизирована обработка скорингов в функции get_text_message для улучшения отладки. - Обновлены тесты для проверки новых функциональных возможностей и обработки ошибок.
This commit is contained in:
123
tests/test_deepseek_service.py
Normal file
123
tests/test_deepseek_service.py
Normal file
@@ -0,0 +1,123 @@
|
||||
"""
|
||||
Тесты для helper_bot.services.scoring.deepseek_service (DeepSeekService).
|
||||
"""
|
||||
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from helper_bot.services.scoring.deepseek_service import DeepSeekService
|
||||
from helper_bot.services.scoring.exceptions import (
|
||||
DeepSeekAPIError,
|
||||
ScoringError,
|
||||
TextTooShortError,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestDeepSeekServiceInit:
|
||||
"""Тесты инициализации DeepSeekService."""
|
||||
|
||||
def test_init_with_api_key_enabled(self):
|
||||
"""При переданном api_key сервис включён."""
|
||||
with patch("helper_bot.services.scoring.deepseek_service.httpx.AsyncClient", None):
|
||||
service = DeepSeekService(api_key="key")
|
||||
assert service.is_enabled is True
|
||||
assert service.source_name == "deepseek"
|
||||
|
||||
def test_init_without_api_key_disabled(self):
|
||||
"""Без api_key сервис отключён."""
|
||||
service = DeepSeekService(api_key=None)
|
||||
assert service.is_enabled is False
|
||||
|
||||
def test_init_default_url_and_model(self):
|
||||
"""Используются DEFAULT_API_URL и DEFAULT_MODEL."""
|
||||
service = DeepSeekService(api_key="k")
|
||||
assert service.api_url == DeepSeekService.DEFAULT_API_URL
|
||||
assert service.model == DeepSeekService.DEFAULT_MODEL
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestDeepSeekServiceHelpers:
|
||||
"""Тесты _clean_text и _parse_score_response."""
|
||||
|
||||
def test_clean_text_strips_and_collapses_whitespace(self):
|
||||
"""_clean_text убирает лишние пробелы и переносы."""
|
||||
service = DeepSeekService(api_key="k")
|
||||
assert service._clean_text(" a b \n c ") == "a b c"
|
||||
|
||||
def test_clean_text_empty_returns_empty(self):
|
||||
"""_clean_text для пустой строки возвращает ''."""
|
||||
service = DeepSeekService(api_key="k")
|
||||
assert service._clean_text("") == ""
|
||||
assert service._clean_text(" ") == ""
|
||||
|
||||
def test_parse_score_response_valid_number(self):
|
||||
"""_parse_score_response парсит число."""
|
||||
service = DeepSeekService(api_key="k")
|
||||
assert service._parse_score_response("0.75") == 0.75
|
||||
assert service._parse_score_response("1.0") == 1.0
|
||||
assert service._parse_score_response("0") == 0.0
|
||||
|
||||
def test_parse_score_response_clamps_to_range(self):
|
||||
"""_parse_score_response ограничивает значение 0.0–1.0."""
|
||||
service = DeepSeekService(api_key="k")
|
||||
assert service._parse_score_response("1.5") == 1.0
|
||||
assert service._parse_score_response("-0.1") == 0.0
|
||||
|
||||
def test_parse_score_response_invalid_raises(self):
|
||||
"""_parse_score_response при невалидном ответе выбрасывает DeepSeekAPIError."""
|
||||
service = DeepSeekService(api_key="k")
|
||||
with pytest.raises(DeepSeekAPIError, match="распарсить"):
|
||||
service._parse_score_response("not a number")
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.asyncio
|
||||
class TestDeepSeekServiceCalculateScore:
|
||||
"""Тесты calculate_score."""
|
||||
|
||||
@pytest.fixture
|
||||
def service(self):
|
||||
"""Сервис с api_key."""
|
||||
return DeepSeekService(api_key="key", min_text_length=3)
|
||||
|
||||
async def test_disabled_raises_scoring_error(self, service):
|
||||
"""При отключённом сервисе — ScoringError."""
|
||||
service._enabled = False
|
||||
with pytest.raises(ScoringError, match="отключен"):
|
||||
await service.calculate_score("достаточно длинный текст")
|
||||
|
||||
async def test_text_too_short_raises(self, service):
|
||||
"""Текст короче min_text_length — TextTooShortError."""
|
||||
with pytest.raises(TextTooShortError, match="короткий"):
|
||||
await service.calculate_score("ab")
|
||||
|
||||
async def test_success_returns_scoring_result(self, service):
|
||||
"""Успешный запрос возвращает ScoringResult."""
|
||||
with patch.object(
|
||||
service,
|
||||
"_make_api_request",
|
||||
new_callable=AsyncMock,
|
||||
return_value=0.82,
|
||||
):
|
||||
result = await service.calculate_score("Текст поста для оценки")
|
||||
|
||||
assert result.score == 0.82
|
||||
assert result.source == "deepseek"
|
||||
assert result.model == service.model
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestDeepSeekServiceStats:
|
||||
"""Тесты get_stats."""
|
||||
|
||||
def test_get_stats_returns_dict(self):
|
||||
"""get_stats возвращает словарь с enabled, model, api_url, timeout, max_retries."""
|
||||
service = DeepSeekService(api_key="k", timeout=60, max_retries=5)
|
||||
stats = service.get_stats()
|
||||
assert stats["enabled"] is True
|
||||
assert stats["model"] == service.model
|
||||
assert stats["api_url"] == service.api_url
|
||||
assert stats["timeout"] == 60
|
||||
assert stats["max_retries"] == 5
|
||||
Reference in New Issue
Block a user