# -*- coding: utf-8 -*- """ Tests für das Google Cloud TTS Plugin. """ import pytest from pathlib import Path from unittest.mock import MagicMock, AsyncMock, patch import importlib.util # Plugin-main.py direkt laden plugin_path = Path(__file__).parent.parent / "main.py" spec = importlib.util.spec_from_file_location("google_tts_plugin", plugin_path) google_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(google_module) GoogleTTSPlugin = google_module.GoogleTTSPlugin GoogleTTSProvider = google_module.GoogleTTSProvider from trixy_core.audio.tts import TTSConfig, TTSState class TestGoogleTTSProvider: """Tests für den GoogleTTSProvider.""" @pytest.fixture def provider(self, tmp_path): """Erstellt einen Provider für Tests.""" config = TTSConfig(language="de-DE", voice_id="de-DE-Wavenet-C") return GoogleTTSProvider( config=config, credentials_path=None, voice_name="de-DE-Wavenet-C", speaking_rate=1.0, pitch=0.0, ) def test_provider_name(self, provider): """Prüft den Provider-Namen.""" assert provider.name == "google" def test_supported_languages(self, provider): """Prüft die unterstützten Sprachen.""" languages = provider.supported_languages assert "de-DE" in languages assert "en-US" in languages assert "fr-FR" in languages assert "ja-JP" in languages def test_supports_streaming(self, provider): """Prüft, dass Streaming nicht unterstützt wird (simuliert).""" assert provider.supports_streaming is False def test_initial_state(self, provider): """Prüft den initialen Zustand.""" assert provider._model_loaded is False assert provider._client is None assert len(provider._available_voices) == 0 def test_speaking_rate_config(self, provider): """Prüft die Sprechrate-Konfiguration.""" assert provider._speaking_rate == 1.0 def test_pitch_config(self, provider): """Prüft die Tonhöhen-Konfiguration.""" assert provider._pitch == 0.0 @pytest.mark.asyncio async def test_synthesize_without_init_raises(self, provider): """Prüft, dass synthesize ohne Initialisierung fehlschlägt.""" with pytest.raises(RuntimeError, match="Google TTS Client nicht initialisiert"): await provider.synthesize("Test") @pytest.mark.asyncio async def test_get_voices_returns_empty_before_init(self, provider): """Prüft, dass get_voices vor Initialisierung leer ist.""" voices = await provider.get_voices() assert len(voices) == 0 class TestGoogleTTSPlugin: """Tests für das GoogleTTSPlugin.""" @pytest.fixture def plugin(self, mock_application, tmp_path): """Erstellt ein Plugin für Tests.""" plugin_path = tmp_path / "tts_google" plugin_path.mkdir() config = { "name": "Google TTS", "enabled": True, "voice": "de-DE-Wavenet-C", "language": "de-DE", "speaking_rate": 1.0, "pitch": 0.0, } return GoogleTTSPlugin(mock_application, plugin_path, config) def test_plugin_initialization(self, plugin): """Prüft die Plugin-Initialisierung.""" assert plugin._provider is None assert plugin.config.get("voice") == "de-DE-Wavenet-C" def test_plugin_path(self, plugin): """Prüft den Plugin-Pfad.""" assert plugin.plugin_path.exists() @pytest.mark.asyncio async def test_on_unload_without_provider(self, plugin): """Prüft on_unload ohne initialisierten Provider.""" await plugin.on_unload() assert plugin._provider is None class TestGoogleTTSVoiceNaming: """Tests für Google TTS Voice-Benennung.""" def test_wavenet_voice_pattern(self): """Prüft das WaveNet-Voice-Benennungsschema.""" voice_name = "de-DE-Wavenet-C" parts = voice_name.split("-") assert len(parts) == 4 assert parts[0] == "de" # Sprache assert parts[1] == "DE" # Region assert parts[2] == "Wavenet" # Typ assert parts[3] == "C" # Variante def test_standard_voice_pattern(self): """Prüft das Standard-Voice-Benennungsschema.""" voice_name = "de-DE-Standard-A" parts = voice_name.split("-") assert parts[2] == "Standard" # Integration Tests (benötigen Google Cloud Credentials) @pytest.mark.integration class TestGoogleTTSIntegration: """Integrationstests für Google TTS (benötigen Credentials).""" @pytest.fixture(autouse=True) def skip_if_not_installed(self): """Überspringt Tests wenn google-cloud-texttospeech nicht installiert ist.""" pytest.importorskip("google.cloud.texttospeech", reason="google-cloud-texttospeech nicht installiert") @pytest.fixture def provider_with_credentials(self, tmp_path): """Erstellt einen Provider mit Credentials.""" config = TTSConfig(language="de-DE", voice_id="de-DE-Wavenet-C") return GoogleTTSProvider( config=config, credentials_path=None, # Nutzt GOOGLE_APPLICATION_CREDENTIALS voice_name="de-DE-Wavenet-C", ) @pytest.mark.asyncio @pytest.mark.slow async def test_full_synthesis_flow(self, provider_with_credentials): """Testet den vollständigen Synthese-Flow.""" await provider_with_credentials.initialize() result = await provider_with_credentials.synthesize("Hallo Welt") assert result.audio_data is not None assert len(result.audio_data) > 0 assert result.sample_rate == 24000 assert result.duration_seconds > 0 assert result.provider == "google" await provider_with_credentials.shutdown()