Spaces:
Build error
Build error
"""Unit tests for ProcessingResult value object.""" | |
import pytest | |
from src.domain.models.processing_result import ProcessingResult | |
from src.domain.models.text_content import TextContent | |
from src.domain.models.audio_content import AudioContent | |
class TestProcessingResult: | |
"""Test cases for ProcessingResult value object.""" | |
def sample_text_content(self): | |
"""Sample text content for testing.""" | |
return TextContent(text="Hello, world!", language="en") | |
def sample_translated_text(self): | |
"""Sample translated text content for testing.""" | |
return TextContent(text="Hola, mundo!", language="es") | |
def sample_audio_content(self): | |
"""Sample audio content for testing.""" | |
return AudioContent( | |
data=b"fake_audio_data", | |
format="wav", | |
sample_rate=22050, | |
duration=5.0 | |
) | |
def test_valid_successful_processing_result(self, sample_text_content, sample_translated_text, sample_audio_content): | |
"""Test creating valid successful ProcessingResult.""" | |
result = ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=sample_translated_text, | |
audio_output=sample_audio_content, | |
error_message=None, | |
processing_time=2.5 | |
) | |
assert result.success is True | |
assert result.original_text == sample_text_content | |
assert result.translated_text == sample_translated_text | |
assert result.audio_output == sample_audio_content | |
assert result.error_message is None | |
assert result.processing_time == 2.5 | |
assert result.has_translation is True | |
assert result.has_audio_output is True | |
assert result.is_complete_pipeline is True | |
def test_valid_failed_processing_result(self): | |
"""Test creating valid failed ProcessingResult.""" | |
result = ProcessingResult( | |
success=False, | |
original_text=None, | |
translated_text=None, | |
audio_output=None, | |
error_message="Processing failed", | |
processing_time=1.0 | |
) | |
assert result.success is False | |
assert result.original_text is None | |
assert result.translated_text is None | |
assert result.audio_output is None | |
assert result.error_message == "Processing failed" | |
assert result.processing_time == 1.0 | |
assert result.has_translation is False | |
assert result.has_audio_output is False | |
assert result.is_complete_pipeline is False | |
def test_non_boolean_success_raises_error(self, sample_text_content): | |
"""Test that non-boolean success raises TypeError.""" | |
with pytest.raises(TypeError, match="Success must be a boolean"): | |
ProcessingResult( | |
success="true", # type: ignore | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=None, | |
error_message=None, | |
processing_time=1.0 | |
) | |
def test_invalid_original_text_type_raises_error(self): | |
"""Test that invalid original text type raises TypeError.""" | |
with pytest.raises(TypeError, match="Original text must be a TextContent instance or None"): | |
ProcessingResult( | |
success=True, | |
original_text="not a TextContent", # type: ignore | |
translated_text=None, | |
audio_output=None, | |
error_message=None, | |
processing_time=1.0 | |
) | |
def test_invalid_translated_text_type_raises_error(self, sample_text_content): | |
"""Test that invalid translated text type raises TypeError.""" | |
with pytest.raises(TypeError, match="Translated text must be a TextContent instance or None"): | |
ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text="not a TextContent", # type: ignore | |
audio_output=None, | |
error_message=None, | |
processing_time=1.0 | |
) | |
def test_invalid_audio_output_type_raises_error(self, sample_text_content): | |
"""Test that invalid audio output type raises TypeError.""" | |
with pytest.raises(TypeError, match="Audio output must be an AudioContent instance or None"): | |
ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output="not an AudioContent", # type: ignore | |
error_message=None, | |
processing_time=1.0 | |
) | |
def test_invalid_error_message_type_raises_error(self, sample_text_content): | |
"""Test that invalid error message type raises TypeError.""" | |
with pytest.raises(TypeError, match="Error message must be a string or None"): | |
ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=None, | |
error_message=123, # type: ignore | |
processing_time=1.0 | |
) | |
def test_non_numeric_processing_time_raises_error(self, sample_text_content): | |
"""Test that non-numeric processing time raises TypeError.""" | |
with pytest.raises(TypeError, match="Processing time must be a number"): | |
ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=None, | |
error_message=None, | |
processing_time="1.0" # type: ignore | |
) | |
def test_negative_processing_time_raises_error(self, sample_text_content): | |
"""Test that negative processing time raises ValueError.""" | |
with pytest.raises(ValueError, match="Processing time cannot be negative"): | |
ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=None, | |
error_message=None, | |
processing_time=-1.0 | |
) | |
def test_successful_result_with_error_message_raises_error(self, sample_text_content): | |
"""Test that successful result with error message raises ValueError.""" | |
with pytest.raises(ValueError, match="Successful result cannot have an error message"): | |
ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=None, | |
error_message="This should not be here", | |
processing_time=1.0 | |
) | |
def test_successful_result_without_original_text_raises_error(self): | |
"""Test that successful result without original text raises ValueError.""" | |
with pytest.raises(ValueError, match="Successful result must have original text"): | |
ProcessingResult( | |
success=True, | |
original_text=None, | |
translated_text=None, | |
audio_output=None, | |
error_message=None, | |
processing_time=1.0 | |
) | |
def test_failed_result_without_error_message_raises_error(self): | |
"""Test that failed result without error message raises ValueError.""" | |
with pytest.raises(ValueError, match="Failed result must have a non-empty error message"): | |
ProcessingResult( | |
success=False, | |
original_text=None, | |
translated_text=None, | |
audio_output=None, | |
error_message=None, | |
processing_time=1.0 | |
) | |
def test_failed_result_with_empty_error_message_raises_error(self): | |
"""Test that failed result with empty error message raises ValueError.""" | |
with pytest.raises(ValueError, match="Failed result must have a non-empty error message"): | |
ProcessingResult( | |
success=False, | |
original_text=None, | |
translated_text=None, | |
audio_output=None, | |
error_message="", | |
processing_time=1.0 | |
) | |
def test_failed_result_with_whitespace_error_message_raises_error(self): | |
"""Test that failed result with whitespace-only error message raises ValueError.""" | |
with pytest.raises(ValueError, match="Failed result must have a non-empty error message"): | |
ProcessingResult( | |
success=False, | |
original_text=None, | |
translated_text=None, | |
audio_output=None, | |
error_message=" ", | |
processing_time=1.0 | |
) | |
def test_has_translation_property(self, sample_text_content, sample_translated_text): | |
"""Test has_translation property.""" | |
# With translation | |
result_with_translation = ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=sample_translated_text, | |
audio_output=None, | |
error_message=None, | |
processing_time=1.0 | |
) | |
assert result_with_translation.has_translation is True | |
# Without translation | |
result_without_translation = ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=None, | |
error_message=None, | |
processing_time=1.0 | |
) | |
assert result_without_translation.has_translation is False | |
def test_has_audio_output_property(self, sample_text_content, sample_audio_content): | |
"""Test has_audio_output property.""" | |
# With audio output | |
result_with_audio = ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=sample_audio_content, | |
error_message=None, | |
processing_time=1.0 | |
) | |
assert result_with_audio.has_audio_output is True | |
# Without audio output | |
result_without_audio = ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=None, | |
error_message=None, | |
processing_time=1.0 | |
) | |
assert result_without_audio.has_audio_output is False | |
def test_is_complete_pipeline_property(self, sample_text_content, sample_translated_text, sample_audio_content): | |
"""Test is_complete_pipeline property.""" | |
# Complete pipeline | |
complete_result = ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=sample_translated_text, | |
audio_output=sample_audio_content, | |
error_message=None, | |
processing_time=1.0 | |
) | |
assert complete_result.is_complete_pipeline is True | |
# Incomplete pipeline (missing translation) | |
incomplete_result = ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=sample_audio_content, | |
error_message=None, | |
processing_time=1.0 | |
) | |
assert incomplete_result.is_complete_pipeline is False | |
# Failed result | |
failed_result = ProcessingResult( | |
success=False, | |
original_text=None, | |
translated_text=None, | |
audio_output=None, | |
error_message="Failed", | |
processing_time=1.0 | |
) | |
assert failed_result.is_complete_pipeline is False | |
def test_success_result_class_method(self, sample_text_content, sample_translated_text, sample_audio_content): | |
"""Test success_result class method.""" | |
result = ProcessingResult.success_result( | |
original_text=sample_text_content, | |
translated_text=sample_translated_text, | |
audio_output=sample_audio_content, | |
processing_time=2.5 | |
) | |
assert result.success is True | |
assert result.original_text == sample_text_content | |
assert result.translated_text == sample_translated_text | |
assert result.audio_output == sample_audio_content | |
assert result.error_message is None | |
assert result.processing_time == 2.5 | |
def test_success_result_with_minimal_parameters(self, sample_text_content): | |
"""Test success_result class method with minimal parameters.""" | |
result = ProcessingResult.success_result( | |
original_text=sample_text_content | |
) | |
assert result.success is True | |
assert result.original_text == sample_text_content | |
assert result.translated_text is None | |
assert result.audio_output is None | |
assert result.error_message is None | |
assert result.processing_time == 0.0 | |
def test_failure_result_class_method(self, sample_text_content): | |
"""Test failure_result class method.""" | |
result = ProcessingResult.failure_result( | |
error_message="Something went wrong", | |
processing_time=1.5, | |
original_text=sample_text_content | |
) | |
assert result.success is False | |
assert result.original_text == sample_text_content | |
assert result.translated_text is None | |
assert result.audio_output is None | |
assert result.error_message == "Something went wrong" | |
assert result.processing_time == 1.5 | |
def test_failure_result_with_minimal_parameters(self): | |
"""Test failure_result class method with minimal parameters.""" | |
result = ProcessingResult.failure_result( | |
error_message="Failed" | |
) | |
assert result.success is False | |
assert result.original_text is None | |
assert result.translated_text is None | |
assert result.audio_output is None | |
assert result.error_message == "Failed" | |
assert result.processing_time == 0.0 | |
def test_processing_result_is_immutable(self, sample_text_content): | |
"""Test that ProcessingResult is immutable (frozen dataclass).""" | |
result = ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=None, | |
error_message=None, | |
processing_time=1.0 | |
) | |
with pytest.raises(AttributeError): | |
result.success = False # type: ignore | |
def test_zero_processing_time_valid(self, sample_text_content): | |
"""Test that zero processing time is valid.""" | |
result = ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=None, | |
error_message=None, | |
processing_time=0.0 | |
) | |
assert result.processing_time == 0.0 | |
def test_partial_success_scenarios(self, sample_text_content, sample_translated_text): | |
"""Test various partial success scenarios.""" | |
# Only STT completed | |
stt_only = ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=None, | |
audio_output=None, | |
error_message=None, | |
processing_time=1.0 | |
) | |
assert stt_only.has_translation is False | |
assert stt_only.has_audio_output is False | |
assert stt_only.is_complete_pipeline is False | |
# STT + Translation completed | |
stt_translation = ProcessingResult( | |
success=True, | |
original_text=sample_text_content, | |
translated_text=sample_translated_text, | |
audio_output=None, | |
error_message=None, | |
processing_time=1.5 | |
) | |
assert stt_translation.has_translation is True | |
assert stt_translation.has_audio_output is False | |
assert stt_translation.is_complete_pipeline is False |