feat: custom voice support, CI pipeline, and Renovate config
Some checks failed
CI / Test (push) Successful in 43s
CI / Lint (push) Successful in 44s
CI / Docker Build & Push (push) Failing after 24s
CI / Notify (push) Successful in 1s
CI / Release (push) Successful in 6s

- VoiceRegistry for trained voices from Kubeflow pipeline
- Custom voice routing in synthesize()
- NATS subjects for listing/refreshing voices
- pyproject.toml with ruff/pytest config
- Full test suite (26 tests)
- Gitea Actions CI (lint, test, docker, notify)
- Renovate config for automated dependency updates

Ref: ADR-0056, ADR-0057
This commit is contained in:
2026-02-13 15:33:27 -05:00
parent d4fafea09b
commit 7b3bfc6812
10 changed files with 1783 additions and 113 deletions

52
tests/conftest.py Normal file
View File

@@ -0,0 +1,52 @@
"""
Pytest configuration and fixtures for tts-module tests.
"""
import asyncio
import os
from unittest.mock import AsyncMock, MagicMock
import pytest
# Set test environment variables before importing
os.environ.setdefault("NATS_URL", "nats://localhost:4222")
os.environ.setdefault("XTTS_URL", "http://localhost:8000")
os.environ.setdefault("OTEL_ENABLED", "false")
os.environ.setdefault("VOICE_MODEL_STORE", "/tmp/test-voice-models")
@pytest.fixture(scope="session")
def event_loop():
"""Create event loop for async tests."""
loop = asyncio.new_event_loop()
yield loop
loop.close()
@pytest.fixture
def sample_audio_bytes():
"""Sample audio bytes for testing (silent 16-bit PCM)."""
return bytes([0x00] * 4096)
@pytest.fixture
def mock_nats():
"""Mock NATS connection."""
nc = AsyncMock()
nc.publish = AsyncMock()
nc.subscribe = AsyncMock()
nc.close = AsyncMock()
return nc
@pytest.fixture
def mock_http_client():
"""Mock httpx async client."""
client = AsyncMock()
response = MagicMock()
response.status_code = 200
response.content = bytes([0x00] * 2048)
response.raise_for_status = MagicMock()
client.post = AsyncMock(return_value=response)
client.aclose = AsyncMock()
return client