telegram.video.summary.bot/tests/test_openai_utils.py

245 lines
9.4 KiB
Python

import pytest
from unittest.mock import patch, MagicMock, AsyncMock
import sys
import os
# Dodanie katalogu nadrzędnego do ścieżki dla importów
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from src.openai_utils import (
summarize_text,
check_openai_api_status,
EmptyTextError,
APIKeyMissingError,
SummarizationError,
QuotaExceededError
)
@pytest.mark.asyncio
async def test_summarize_text_success():
# Przygotowanie mocka dla odpowiedzi OpenAI
mock_choice = MagicMock()
mock_message = MagicMock()
mock_message.content = "To jest przykładowe streszczenie filmu."
mock_choice.message = mock_message
mock_response = MagicMock()
mock_response.choices = [mock_choice]
# Testowy tekst transkrypcji
test_transcript = "To jest przykładowa transkrypcja filmu YouTube, " \
"która zostanie wysłana do API OpenAI w celu streszczenia. " \
"Zawiera kilka zdań o różnej tematyce."
# Test funkcji z mockiem
with patch('src.openai_utils.client') as mock_client:
mock_client.chat.completions.create = AsyncMock(return_value=mock_response)
result = await summarize_text(test_transcript)
# Sprawdzenie wyników
assert result == "To jest przykładowe streszczenie filmu."
assert mock_client.chat.completions.create.called
# Sprawdzenie czy parametry zostały przekazane poprawnie
call_args = mock_client.chat.completions.create.call_args[1]
assert call_args['model'] == "gpt-4o-mini" # Zaktualizowano model
assert call_args['temperature'] == 0.5
assert call_args['max_tokens'] == 150
# Sprawdzenie wiadomości
messages = call_args['messages']
assert len(messages) == 2
assert messages[0]['role'] == "system"
assert messages[1]['role'] == "user"
assert test_transcript in messages[1]['content'] # Sprawdzenie czy transkrypcja jest w prompcie
@pytest.mark.asyncio
async def test_summarize_text_with_transcript_from_youtube():
# Przygotowanie mocka dla odpowiedzi OpenAI
mock_choice = MagicMock()
mock_message = MagicMock()
mock_message.content = "Film przedstawia dyskusję na temat sztucznej inteligencji i jej zastosowań w życiu codziennym."
mock_choice.message = mock_message
mock_response = MagicMock()
mock_response.choices = [mock_choice]
# Przykładowa transkrypcja z YouTube
youtube_transcript = "To jest przykładowa transkrypcja z YouTube. " \
"Zawiera dyskusję o sztucznej inteligencji. " \
"Przedstawia różne zastosowania AI w codziennym życiu."
# Test funkcji
with patch('src.openai_utils.client') as mock_client:
mock_client.chat.completions.create = AsyncMock(return_value=mock_response)
result = await summarize_text(youtube_transcript)
# Sprawdzenie wyników
assert result == "Film przedstawia dyskusję na temat sztucznej inteligencji i jej zastosowań w życiu codziennym."
assert mock_client.chat.completions.create.called
@pytest.mark.asyncio
async def test_summarize_empty_text():
# Test funkcji z pustym tekstem
with patch('src.openai_utils.client.chat.completions.create') as mock_create:
# Powinien rzucić EmptyTextError dla pustego tekstu
with pytest.raises(EmptyTextError):
await summarize_text("")
# Sprawdzenie czy mock nie został wywołany
assert not mock_create.called
@pytest.mark.asyncio
async def test_summarize_text_api_error():
# Symulacja błędu API
with patch('src.openai_utils.client') as mock_client:
mock_client.chat.completions.create = AsyncMock(side_effect=Exception("API Error"))
# Test funkcji - powinien rzucić SummarizationError
with pytest.raises(SummarizationError) as excinfo:
await summarize_text("Jakiś tekst transkrypcji")
# Sprawdzenie czy wiadomość błędu zawiera oryginalne informacje
assert "API Error" in str(excinfo.value)
assert mock_client.chat.completions.create.called
@pytest.mark.asyncio
async def test_summarize_text_quota_exceeded_error():
# Symulacja błędu przekroczenia limitu
error_response = Exception("Error code: 429 - {'error': {'message': 'You exceeded your current quota', 'type': 'insufficient_quota'}}")
with patch('src.openai_utils.client') as mock_client:
mock_client.chat.completions.create = AsyncMock(side_effect=error_response)
# Test funkcji - powinien rzucić QuotaExceededError
with pytest.raises(QuotaExceededError) as excinfo:
await summarize_text("Jakiś tekst transkrypcji")
# Sprawdzenie czy wiadomość błędu zawiera informację o limicie
assert "Przekroczono limit zapytań API OpenAI" in str(excinfo.value)
assert mock_client.chat.completions.create.called
@pytest.mark.asyncio
async def test_summarize_text_no_client():
# Symulacja braku klienta OpenAI
with patch('src.openai_utils.client', None):
# Test funkcji - powinien rzucić APIKeyMissingError
with pytest.raises(APIKeyMissingError):
await summarize_text("Jakiś tekst transkrypcji")
@pytest.mark.asyncio
async def test_summarize_text_prompt_format():
# Przygotowanie mocka
mock_choice = MagicMock()
mock_message = MagicMock()
mock_message.content = "Streszczenie"
mock_choice.message = mock_message
mock_response = MagicMock()
mock_response.choices = [mock_choice]
# Testowy tekst
test_transcript = "Testowa transkrypcja"
# Przygotowanie spy do przechwycenia argumentów
with patch('src.openai_utils.client') as mock_client:
mock_client.chat.completions.create = AsyncMock(return_value=mock_response)
# Test funkcji
await summarize_text(test_transcript)
# Sprawdzenie czy został wywołany
assert mock_client.chat.completions.create.called
# Pobranie argumentów wywołania
call_args = mock_client.chat.completions.create.call_args[1]
messages = call_args['messages']
# Sprawdzenie czy prompt zawiera odpowiedni format
user_prompt = messages[1]['content']
assert "Streść poniższy transkrypt filmu z YouTube" in user_prompt
assert "Transkrypt:" in user_prompt
assert test_transcript in user_prompt
@pytest.mark.asyncio
async def test_check_openai_api_status_success():
# Przygotowanie mocka dla udanej odpowiedzi
mock_choice = MagicMock()
mock_message = MagicMock()
mock_message.content = "Hello"
mock_choice.message = mock_message
mock_response = MagicMock()
mock_response.choices = [mock_choice]
mock_response.usage = MagicMock(_asdict=lambda: {"prompt_tokens": 20, "completion_tokens": 5, "total_tokens": 25})
mock_response.organization_id = "org-123"
with patch('src.openai_utils.client') as mock_client:
mock_client.chat.completions.create = AsyncMock(return_value=mock_response)
# Test funkcji
available, status_info = await check_openai_api_status()
# Sprawdzenie wyników
assert available == True
assert status_info["available"] == True
assert status_info["model"] == "gpt-4o-mini"
assert status_info["organization_id"] == "org-123"
assert "usage" in status_info
assert status_info["usage"]["total_tokens"] == 25
assert mock_client.chat.completions.create.called
@pytest.mark.asyncio
async def test_check_openai_api_status_quota_exceeded():
# Symulacja błędu przekroczenia limitu
error_response = Exception("Error code: 429 - {'error': {'message': 'You exceeded your current quota', 'type': 'insufficient_quota'}}")
with patch('src.openai_utils.client') as mock_client:
mock_client.chat.completions.create = AsyncMock(side_effect=error_response)
# Test funkcji - powinien rzucić QuotaExceededError
with pytest.raises(QuotaExceededError) as excinfo:
await check_openai_api_status()
# Sprawdzenie czy wiadomość błędu zawiera informację o limicie
assert "Przekroczono limit zapytań API OpenAI" in str(excinfo.value)
assert mock_client.chat.completions.create.called
@pytest.mark.asyncio
async def test_check_openai_api_status_no_client():
# Symulacja braku klienta OpenAI
with patch('src.openai_utils.client', None):
# Test funkcji - powinien rzucić APIKeyMissingError
with pytest.raises(APIKeyMissingError):
await check_openai_api_status()
@pytest.mark.asyncio
async def test_check_openai_api_status_api_error():
# Symulacja ogólnego błędu API
with patch('src.openai_utils.client') as mock_client:
mock_client.chat.completions.create = AsyncMock(side_effect=Exception("General API Error"))
# Test funkcji - nie powinien rzucać wyjątku
available, status_info = await check_openai_api_status()
# Sprawdzenie wyników
assert available == False
assert status_info["available"] == False
assert "error" in status_info
assert "General API Error" in status_info["error"]
assert mock_client.chat.completions.create.called