253 lines
11 KiB
Python
253 lines
11 KiB
Python
import pytest
|
|
import os
|
|
import sys
|
|
import asyncio
|
|
import logging
|
|
from dotenv import load_dotenv
|
|
|
|
# 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.youtube_utils import (
|
|
extract_youtube_urls,
|
|
extract_video_id,
|
|
get_transcript,
|
|
NoTranscriptFound,
|
|
TranscriptsDisabled,
|
|
APITokenMissing,
|
|
AuthorizationError,
|
|
APIConnectionError,
|
|
APIResponseError,
|
|
NoTranscriptLanguagesAvailable,
|
|
YouTubeUtilsError
|
|
)
|
|
from src.openai_utils import summarize_text
|
|
|
|
# Konfiguracja logowania dla testów
|
|
logging.basicConfig(
|
|
level=logging.DEBUG,
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Ładowanie zmiennych środowiskowych z pliku .env (jeśli istnieje)
|
|
load_dotenv()
|
|
|
|
# Zmiana na bardziej popularne wideo, które powinno być bardziej stabilne
|
|
# "What makes a good life? Lessons from the longest study on happiness | Robert Waldinger"
|
|
# TED Talk - bardzo popularne wystąpienie z napisami w wielu językach (>42M wyświetleń)
|
|
TEST_VIDEO_URL = "https://www.youtube.com/watch?v=8KkKuTCFvzI"
|
|
TEST_VIDEO_ID = extract_video_id(TEST_VIDEO_URL)
|
|
TEST_LANGUAGES = ["pl", "en"] # Preferujemy polską transkrypcję, potem angielską
|
|
|
|
# Drugi film zapasowy (na wypadek problemów z pierwszym)
|
|
BACKUP_VIDEO_URL = "https://www.youtube.com/watch?v=jNQXAC9IVRw" # Me at the zoo - pierwszy film na YouTube
|
|
BACKUP_VIDEO_ID = extract_video_id(BACKUP_VIDEO_URL)
|
|
|
|
# Oznaczamy testy jako "slow", żeby można było je pominąć za pomocą --skip-slow
|
|
# lub --skip-integration podczas uruchamiania testów
|
|
pytestmark = [pytest.mark.integration, pytest.mark.slow]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_real_extract_youtube_urls():
|
|
# Test na rzeczywistym tekście z linkami YouTube
|
|
text = """Sprawdź te filmy:
|
|
- https://www.youtube.com/watch?v=8KkKuTCFvzI
|
|
- https://youtu.be/iCvmsMzlF7o
|
|
- Również shorts: https://www.youtube.com/shorts/pFaEGmxQFnM"""
|
|
|
|
urls = extract_youtube_urls(text)
|
|
assert len(urls) == 3
|
|
assert "https://www.youtube.com/watch?v=8KkKuTCFvzI" in urls
|
|
assert "https://youtu.be/iCvmsMzlF7o" in urls
|
|
assert "https://www.youtube.com/shorts/pFaEGmxQFnM" in urls
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_real_extract_video_id():
|
|
# Test na rzeczywistych URL-ach
|
|
assert extract_video_id("https://www.youtube.com/watch?v=8KkKuTCFvzI") == "8KkKuTCFvzI"
|
|
assert extract_video_id("https://youtu.be/iCvmsMzlF7o") == "iCvmsMzlF7o"
|
|
assert extract_video_id("https://www.youtube.com/shorts/pFaEGmxQFnM") == "pFaEGmxQFnM"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_real_get_transcript_and_title():
|
|
"""Test pobierania rzeczywistej transkrypcji i tytułu"""
|
|
# Ten test wymaga dostępu do internetu i tokenu API youtube-transcript.io
|
|
|
|
# Sprawdź czy mamy token API
|
|
from src.config import YOUTUBE_TRANSCRIPT_API_TOKEN
|
|
if not YOUTUBE_TRANSCRIPT_API_TOKEN:
|
|
pytest.skip("Brak tokenu API youtube-transcript.io")
|
|
|
|
# Wypróbuj główne wideo
|
|
logger.info(f"Próbuję pobrać transkrypcję dla głównego wideo: {TEST_VIDEO_ID}")
|
|
|
|
try:
|
|
# Spróbuj z pierwszym filmem
|
|
transcript, title = await get_transcript(TEST_VIDEO_ID, TEST_LANGUAGES)
|
|
assert len(transcript) > 100 # Upewniamy się, że transkrypcja ma sensowną długość
|
|
assert len(title) > 0 # Tytuł powinien być niepusty
|
|
|
|
# Wypiszmy tytuł i fragment transkrypcji do weryfikacji
|
|
logger.info(f"Tytuł filmu {TEST_VIDEO_ID}: {title}")
|
|
logger.info(f"Fragment transkrypcji: {transcript[:50]}...")
|
|
|
|
except (NoTranscriptFound, TranscriptsDisabled) as e:
|
|
logger.warning(f"Nie udało się pobrać transkrypcji dla {TEST_VIDEO_ID}: {e}")
|
|
logger.info(f"Próbuję film zapasowy: {BACKUP_VIDEO_ID}")
|
|
|
|
# Spróbuj z zapasowym filmem
|
|
try:
|
|
transcript, title = await get_transcript(BACKUP_VIDEO_ID, TEST_LANGUAGES)
|
|
assert len(transcript) > 10 # Film zapasowy "Me at the zoo" ma bardzo krótką transkrypcję
|
|
assert len(title) > 0
|
|
|
|
# Wypiszmy tytuł i fragment transkrypcji do weryfikacji
|
|
logger.info(f"Tytuł filmu zapasowego {BACKUP_VIDEO_ID}: {title}")
|
|
logger.info(f"Fragment transkrypcji zapasowej: {transcript[:50]}...")
|
|
|
|
except (NoTranscriptFound, TranscriptsDisabled) as e:
|
|
logger.error(f"Nie można pobrać transkrypcji dla żadnego z testowych filmów: {e}")
|
|
pytest.skip(f"Nie można pobrać transkrypcji dla żadnego z testowych filmów: {e}")
|
|
|
|
except (APITokenMissing, AuthorizationError) as e:
|
|
logger.error(f"Błąd autoryzacji: {e}")
|
|
pytest.skip(f"Błąd autoryzacji API: {e}")
|
|
|
|
except (APIConnectionError, APIResponseError) as e:
|
|
logger.error(f"Błąd API: {e}")
|
|
pytest.skip(f"Błąd API: {e}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Nieoczekiwany błąd podczas pobierania transkrypcji: {e}", exc_info=True)
|
|
pytest.skip(f"Nieoczekiwany błąd podczas pobierania transkrypcji: {e}")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.skipif(not os.environ.get("OPENAI_API_KEY"), reason="Wymaga klucza API OpenAI")
|
|
async def test_real_summarize_text():
|
|
# Test rzeczywistego streszczania tekstu z OpenAI API
|
|
# Ten test wymaga klucza API OpenAI
|
|
|
|
# Użyjmy krótkiej transkrypcji dla oszczędności tokenów
|
|
short_transcript = """
|
|
Chciałbym porozmawiać o tym, co sprawia, że życie jest dobre i wartościowe.
|
|
Przeprowadziliśmy jedno z najdłuższych badań nad szczęściem - trwające ponad 75 lat.
|
|
Badaliśmy życie tych samych osób od czasu, gdy byli nastolatkami, aż do starości.
|
|
Wniosek? Dobre relacje z innymi ludźmi są kluczem do szczęścia i zdrowia.
|
|
Nie pieniądze, nie sława, nie ciężka praca, ale jakość naszych relacji z bliskimi.
|
|
Osoby, które miały dobre relacje z rodziną, przyjaciółmi i społecznością,
|
|
były szczęśliwsze, zdrowsze i żyły dłużej.
|
|
"""
|
|
|
|
logger.info("Próbuję streszczenie transkrypcji za pomocą OpenAI API")
|
|
|
|
try:
|
|
summary = await summarize_text(short_transcript)
|
|
assert summary is not None
|
|
assert len(summary) > 0
|
|
|
|
logger.info(f"Wygenerowane streszczenie: {summary}")
|
|
except Exception as e:
|
|
logger.error(f"Problem z API OpenAI: {e}", exc_info=True)
|
|
pytest.skip(f"Problem z API OpenAI: {e}")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.skipif(not os.environ.get("OPENAI_API_KEY") or not os.environ.get("YOUTUBE_TRANSCRIPT_API_TOKEN"),
|
|
reason="Wymaga klucza API OpenAI i tokenu API youtube-transcript.io")
|
|
async def test_end_to_end_integration():
|
|
"""
|
|
Ten test wykonuje pełną integrację od linku YouTube do streszczenia.
|
|
Wymaga dostępu do internetu, tokenu API youtube-transcript.io oraz klucza API OpenAI.
|
|
"""
|
|
logger.info("Rozpoczynam test integracyjny end-to-end")
|
|
|
|
# Testujemy na klasycznym filmie "Me at the zoo", który jest krótki i ma dostępne transkrypcje
|
|
text_with_url = f"Sprawdź ten film: {BACKUP_VIDEO_URL}"
|
|
|
|
# 1. Wydobycie URL
|
|
urls = extract_youtube_urls(text_with_url)
|
|
assert len(urls) == 1
|
|
url = urls[0]
|
|
logger.info(f"Znaleziono URL: {url}")
|
|
|
|
# 2. Wydobycie ID filmu
|
|
video_id = extract_video_id(url)
|
|
assert video_id == BACKUP_VIDEO_ID
|
|
logger.info(f"ID filmu: {video_id}")
|
|
|
|
# 3. Pobranie transkrypcji i tytułu
|
|
try:
|
|
logger.info(f"Próbuję pobrać transkrypcję dla {video_id}")
|
|
transcript, title = await get_transcript(video_id, TEST_LANGUAGES)
|
|
|
|
logger.info(f"Pobrano tytuł filmu: {title}")
|
|
logger.info(f"Długość transkrypcji: {len(transcript)} znaków")
|
|
logger.info(f"Fragment transkrypcji: {transcript[:150]}...")
|
|
|
|
# Weryfikacja tytułu dla "Me at the zoo"
|
|
assert "Me at the zoo" in title
|
|
|
|
except (NoTranscriptFound, TranscriptsDisabled, APIConnectionError, APIResponseError) as e:
|
|
logger.warning(f"Nie udało się pobrać transkrypcji dla {video_id}: {e}")
|
|
|
|
# Jeśli wystąpił wyjątek, spróbuj z głównym filmem
|
|
logger.info(f"Próbuję główny film: {TEST_VIDEO_ID}")
|
|
|
|
try:
|
|
transcript, title = await get_transcript(TEST_VIDEO_ID, TEST_LANGUAGES)
|
|
|
|
logger.info(f"Pobrano tytuł głównego filmu: {title}")
|
|
logger.info(f"Długość transkrypcji: {len(transcript)} znaków")
|
|
logger.info(f"Fragment transkrypcji: {transcript[:150]}...")
|
|
|
|
except (NoTranscriptFound, TranscriptsDisabled, APIConnectionError, APIResponseError) as e:
|
|
logger.error(f"Nie można pobrać transkrypcji dla żadnego z testowych filmów: {e}")
|
|
pytest.skip(f"Nie można pobrać transkrypcji dla żadnego z testowych filmów: {e}")
|
|
|
|
# 4. Skrócenie transkrypcji dla oszczędności tokenów (tylko dla testu)
|
|
# "Me at the zoo" ma wystarczająco krótką transkrypcję, więc możemy użyć całości
|
|
logger.info(f"Długość oryginalnej transkrypcji: {len(transcript)} znaków")
|
|
|
|
# 5. Wygenerowanie streszczenia
|
|
try:
|
|
logger.info("Próbuję wygenerować streszczenie")
|
|
|
|
summary = await summarize_text(transcript)
|
|
assert summary is not None
|
|
assert len(summary) > 10
|
|
|
|
logger.info(f"Wygenerowane streszczenie: {summary}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Błąd podczas generowania streszczenia: {e}", exc_info=True)
|
|
pytest.skip(f"Błąd podczas generowania streszczenia: {e}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Możliwość uruchomienia testów bezpośrednio z tego pliku
|
|
asyncio.run(test_real_extract_youtube_urls())
|
|
asyncio.run(test_real_extract_video_id())
|
|
|
|
# Testy wymagające połączenia z YouTube
|
|
try:
|
|
asyncio.run(test_real_get_transcript_and_title())
|
|
except Exception as e:
|
|
logger.error(f"Problemy z połączeniem z YouTube API: {e}", exc_info=True)
|
|
|
|
# Testy wymagające klucza API OpenAI
|
|
if os.environ.get("OPENAI_API_KEY"):
|
|
try:
|
|
asyncio.run(test_real_summarize_text())
|
|
if os.environ.get("YOUTUBE_TRANSCRIPT_API_TOKEN"):
|
|
asyncio.run(test_end_to_end_integration())
|
|
else:
|
|
logger.warning("Pominięto test end-to-end (brak tokenu API youtube-transcript.io)")
|
|
except Exception as e:
|
|
logger.error(f"Problemy z OpenAI API: {e}", exc_info=True)
|
|
else:
|
|
logger.warning("Pominięto testy OpenAI (brak klucza API)") |