124 lines
4.2 KiB
Python
124 lines
4.2 KiB
Python
from fastapi.testclient import TestClient
|
|
import pytest
|
|
# from main import app, ENGINE_REGISTRY # No longer needed, using fixtures
|
|
import shutil
|
|
import asyncio
|
|
|
|
TEST_TEXT = "Dies ist ein NovaAi Test."
|
|
# Ensure the engine being tested is in the default .env config
|
|
ENGINE = "piper"
|
|
MODEL = "de_DE-thorsten-high"
|
|
FORMAT = "ogg"
|
|
|
|
# === Happy Path Tests ===
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_tts_link_success(app_client):
|
|
"""Tests successful synthesis returning a URL."""
|
|
resp = app_client.post("/tts", json={
|
|
"text": TEST_TEXT,
|
|
"engine": ENGINE,
|
|
"model": MODEL,
|
|
"format": FORMAT
|
|
})
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert "audio_url" in data
|
|
|
|
# Also test the audio download endpoint
|
|
audio_url = data['audio_url']
|
|
audio_resp = app_client.get(audio_url)
|
|
assert audio_resp.status_code == 200
|
|
assert len(audio_resp.content) > 1000
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_tts_base64_success(app_client):
|
|
"""Tests successful synthesis returning base64 data."""
|
|
resp = app_client.post("/tts?as=true", json={
|
|
"text": TEST_TEXT,
|
|
"engine": ENGINE,
|
|
"model": MODEL,
|
|
"format": FORMAT
|
|
})
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert "audio_base64" in data
|
|
assert len(data["audio_base64"]) > 1000
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_health_and_engines_endpoints(app_client):
|
|
"""Tests the /health and /engines endpoints for correct responses."""
|
|
resp_engines = app_client.get("/engines")
|
|
assert resp_engines.status_code == 200
|
|
engines = resp_engines.json()
|
|
assert ENGINE in engines
|
|
|
|
resp_health = app_client.get("/health")
|
|
assert resp_health.status_code == 200
|
|
health = resp_health.json()
|
|
assert health["status"][ENGINE] == "ok"
|
|
|
|
# === Failure Path Tests ===
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_tts_fails_with_invalid_engine(app_client):
|
|
"""Tests that a request with a non-existent engine fails with HTTP 404."""
|
|
response = app_client.post("/tts", json={
|
|
"text": TEST_TEXT,
|
|
"engine": "non_existent_engine",
|
|
"model": MODEL,
|
|
})
|
|
assert response.status_code == 404
|
|
assert "Engine 'non_existent_engine' not found" in response.json()["detail"]
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_tts_fails_with_invalid_model(app_client):
|
|
"""Tests that a request with a non-existent model fails with HTTP 400."""
|
|
response = app_client.post("/tts", json={
|
|
"text": TEST_TEXT,
|
|
"engine": ENGINE,
|
|
"model": "non_existent_model",
|
|
})
|
|
assert response.status_code == 400
|
|
assert "Model 'non_existent_model' not found" in response.json()["detail"]
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_tts_fails_with_invalid_speaker(app_client, piper_engine):
|
|
"""Tests that a request with a non-existent speaker fails with HTTP 400."""
|
|
# This model has speakers, so requesting a non-existent one should fail.
|
|
# We need to pick a model that is known to have multiple speakers
|
|
# The default piper engine models should have this.
|
|
model_with_speakers = "en_US-kristin-medium" # Example model with speakers
|
|
|
|
# First, check if the model is actually available to test against
|
|
if model_with_speakers not in piper_engine.list_models():
|
|
pytest.skip(f"Model '{model_with_speakers}' not available for '{ENGINE}' to test against.")
|
|
|
|
response = app_client.post("/tts", json={
|
|
"text": "This is a test.",
|
|
"engine": ENGINE,
|
|
"model": model_with_speakers,
|
|
"speaker": "non_existent_speaker"
|
|
})
|
|
assert response.status_code == 400
|
|
assert "Speaker 'non_existent_speaker' not found" in response.json()["detail"]
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_tts_fails_with_unavailable_engine(app_client, piper_engine, monkeypatch):
|
|
"""Tests that a request fails with HTTP 503 if an engine is unhealthy."""
|
|
# Simulate the piper executable being not found by monkeypatching the specific instance
|
|
monkeypatch.setattr(piper_engine, "piper_executable", None)
|
|
|
|
response = app_client.post("/tts", json={
|
|
"text": TEST_TEXT,
|
|
"engine": ENGINE,
|
|
"model": MODEL,
|
|
})
|
|
|
|
assert response.status_code == 503
|
|
assert "is not available" in response.json()["detail"]
|
|
|
|
|
|
|
|
|