Spaces:
Build error
Build error
"""Unit tests for ProcessingRequestDto""" | |
import pytest | |
from src.application.dtos.processing_request_dto import ProcessingRequestDto | |
from src.application.dtos.audio_upload_dto import AudioUploadDto | |
class TestProcessingRequestDto: | |
"""Test cases for ProcessingRequestDto""" | |
def sample_audio_upload(self): | |
"""Create sample audio upload DTO""" | |
return AudioUploadDto( | |
filename="test_audio.wav", | |
content=b"fake_audio_content_" + b"x" * 1000, | |
content_type="audio/wav" | |
) | |
def test_valid_processing_request_dto(self, sample_audio_upload): | |
"""Test creating a valid ProcessingRequestDto""" | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="kokoro", | |
speed=1.0, | |
source_language="en" | |
) | |
assert dto.audio == sample_audio_upload | |
assert dto.asr_model == "whisper-small" | |
assert dto.target_language == "es" | |
assert dto.voice == "kokoro" | |
assert dto.speed == 1.0 | |
assert dto.source_language == "en" | |
assert dto.additional_params == {} | |
def test_processing_request_dto_with_defaults(self, sample_audio_upload): | |
"""Test creating ProcessingRequestDto with default values""" | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-medium", | |
target_language="fr", | |
voice="dia" | |
) | |
assert dto.speed == 1.0 # Default speed | |
assert dto.source_language is None # Default source language | |
assert dto.additional_params == {} # Default additional params | |
def test_processing_request_dto_with_additional_params(self, sample_audio_upload): | |
"""Test creating ProcessingRequestDto with additional parameters""" | |
additional_params = { | |
"custom_param": "value", | |
"another_param": 123 | |
} | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-large", | |
target_language="de", | |
voice="cosyvoice2", | |
additional_params=additional_params | |
) | |
assert dto.additional_params == additional_params | |
def test_invalid_audio_type_validation(self): | |
"""Test validation with invalid audio type""" | |
with pytest.raises(ValueError, match="Audio must be an AudioUploadDto instance"): | |
ProcessingRequestDto( | |
audio="invalid_audio", # Not AudioUploadDto | |
asr_model="whisper-small", | |
target_language="es", | |
voice="kokoro" | |
) | |
def test_empty_asr_model_validation(self, sample_audio_upload): | |
"""Test validation with empty ASR model""" | |
with pytest.raises(ValueError, match="ASR model cannot be empty"): | |
ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="", | |
target_language="es", | |
voice="kokoro" | |
) | |
def test_unsupported_asr_model_validation(self, sample_audio_upload): | |
"""Test validation with unsupported ASR model""" | |
with pytest.raises(ValueError, match="Unsupported ASR model"): | |
ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="invalid-model", | |
target_language="es", | |
voice="kokoro" | |
) | |
def test_supported_asr_models(self, sample_audio_upload): | |
"""Test all supported ASR models""" | |
supported_models = ['whisper-small', 'whisper-medium', 'whisper-large', 'parakeet'] | |
for model in supported_models: | |
# Should not raise exception | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model=model, | |
target_language="es", | |
voice="kokoro" | |
) | |
assert dto.asr_model == model | |
def test_empty_target_language_validation(self, sample_audio_upload): | |
"""Test validation with empty target language""" | |
with pytest.raises(ValueError, match="Target language cannot be empty"): | |
ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="", | |
voice="kokoro" | |
) | |
def test_unsupported_target_language_validation(self, sample_audio_upload): | |
"""Test validation with unsupported target language""" | |
with pytest.raises(ValueError, match="Unsupported target language"): | |
ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="invalid-lang", | |
voice="kokoro" | |
) | |
def test_unsupported_source_language_validation(self, sample_audio_upload): | |
"""Test validation with unsupported source language""" | |
with pytest.raises(ValueError, match="Unsupported source language"): | |
ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="kokoro", | |
source_language="invalid-lang" | |
) | |
def test_supported_languages(self, sample_audio_upload): | |
"""Test all supported languages""" | |
supported_languages = [ | |
'en', 'es', 'fr', 'de', 'it', 'pt', 'ru', 'ja', 'ko', 'zh', | |
'ar', 'hi', 'tr', 'pl', 'nl', 'sv', 'da', 'no', 'fi' | |
] | |
for lang in supported_languages: | |
# Should not raise exception | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language=lang, | |
voice="kokoro", | |
source_language=lang | |
) | |
assert dto.target_language == lang | |
assert dto.source_language == lang | |
def test_empty_voice_validation(self, sample_audio_upload): | |
"""Test validation with empty voice""" | |
with pytest.raises(ValueError, match="Voice cannot be empty"): | |
ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="" | |
) | |
def test_unsupported_voice_validation(self, sample_audio_upload): | |
"""Test validation with unsupported voice""" | |
with pytest.raises(ValueError, match="Unsupported voice"): | |
ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="invalid-voice" | |
) | |
def test_supported_voices(self, sample_audio_upload): | |
"""Test all supported voices""" | |
supported_voices = ['kokoro', 'dia', 'cosyvoice2', 'dummy'] | |
for voice in supported_voices: | |
# Should not raise exception | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice=voice | |
) | |
assert dto.voice == voice | |
def test_speed_range_validation_too_low(self, sample_audio_upload): | |
"""Test validation with speed too low""" | |
with pytest.raises(ValueError, match="Speed must be between 0.5 and 2.0"): | |
ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="kokoro", | |
speed=0.3 # Too low | |
) | |
def test_speed_range_validation_too_high(self, sample_audio_upload): | |
"""Test validation with speed too high""" | |
with pytest.raises(ValueError, match="Speed must be between 0.5 and 2.0"): | |
ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="kokoro", | |
speed=2.5 # Too high | |
) | |
def test_valid_speed_range(self, sample_audio_upload): | |
"""Test valid speed range""" | |
valid_speeds = [0.5, 1.0, 1.5, 2.0] | |
for speed in valid_speeds: | |
# Should not raise exception | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="kokoro", | |
speed=speed | |
) | |
assert dto.speed == speed | |
def test_invalid_additional_params_type(self, sample_audio_upload): | |
"""Test validation with invalid additional params type""" | |
with pytest.raises(ValueError, match="Additional params must be a dictionary"): | |
ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="kokoro", | |
additional_params="invalid" # Not a dict | |
) | |
def test_requires_translation_property_same_language(self, sample_audio_upload): | |
"""Test requires_translation property when source and target are same""" | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="en", | |
voice="kokoro", | |
source_language="en" | |
) | |
assert dto.requires_translation is False | |
def test_requires_translation_property_different_languages(self, sample_audio_upload): | |
"""Test requires_translation property when source and target are different""" | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="kokoro", | |
source_language="en" | |
) | |
assert dto.requires_translation is True | |
def test_requires_translation_property_no_source(self, sample_audio_upload): | |
"""Test requires_translation property when no source language specified""" | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="kokoro" | |
) | |
assert dto.requires_translation is True # Assume translation needed | |
def test_to_dict_method(self, sample_audio_upload): | |
"""Test to_dict method""" | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="kokoro", | |
speed=1.5, | |
source_language="en", | |
additional_params={"custom": "value"} | |
) | |
result = dto.to_dict() | |
assert result['audio'] == sample_audio_upload.to_dict() | |
assert result['asr_model'] == "whisper-small" | |
assert result['target_language'] == "es" | |
assert result['source_language'] == "en" | |
assert result['voice'] == "kokoro" | |
assert result['speed'] == 1.5 | |
assert result['requires_translation'] is True | |
assert result['additional_params'] == {"custom": "value"} | |
def test_from_dict_method(self, sample_audio_upload): | |
"""Test from_dict class method""" | |
data = { | |
'audio': sample_audio_upload, | |
'asr_model': 'whisper-medium', | |
'target_language': 'fr', | |
'voice': 'dia', | |
'speed': 1.2, | |
'source_language': 'en', | |
'additional_params': {'test': 'value'} | |
} | |
dto = ProcessingRequestDto.from_dict(data) | |
assert dto.audio == sample_audio_upload | |
assert dto.asr_model == 'whisper-medium' | |
assert dto.target_language == 'fr' | |
assert dto.voice == 'dia' | |
assert dto.speed == 1.2 | |
assert dto.source_language == 'en' | |
assert dto.additional_params == {'test': 'value'} | |
def test_from_dict_method_with_audio_dict(self): | |
"""Test from_dict method with audio as dictionary""" | |
audio_data = { | |
'filename': 'test.wav', | |
'content': b'fake_content' + b'x' * 1000, | |
'content_type': 'audio/wav' | |
} | |
data = { | |
'audio': audio_data, | |
'asr_model': 'whisper-small', | |
'target_language': 'es', | |
'voice': 'kokoro' | |
} | |
dto = ProcessingRequestDto.from_dict(data) | |
assert isinstance(dto.audio, AudioUploadDto) | |
assert dto.audio.filename == 'test.wav' | |
assert dto.audio.content_type == 'audio/wav' | |
def test_from_dict_method_with_defaults(self, sample_audio_upload): | |
"""Test from_dict method with default values""" | |
data = { | |
'audio': sample_audio_upload, | |
'asr_model': 'whisper-small', | |
'target_language': 'es', | |
'voice': 'kokoro' | |
} | |
dto = ProcessingRequestDto.from_dict(data) | |
assert dto.speed == 1.0 # Default | |
assert dto.source_language is None # Default | |
assert dto.additional_params is None # Default | |
def test_validation_called_on_init(self, sample_audio_upload): | |
"""Test that validation is called during initialization""" | |
# This should trigger validation and raise an error | |
with pytest.raises(ValueError): | |
ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="", # Invalid empty model | |
target_language="es", | |
voice="kokoro" | |
) | |
def test_additional_params_default_initialization(self, sample_audio_upload): | |
"""Test that additional_params is initialized to empty dict if None""" | |
dto = ProcessingRequestDto( | |
audio=sample_audio_upload, | |
asr_model="whisper-small", | |
target_language="es", | |
voice="kokoro", | |
additional_params=None | |
) | |
assert dto.additional_params == {} |