teachingAssistant / tests /unit /domain /models /test_processing_result.py
Michael Hu
Create unit tests for domain layer
48f8a08
"""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."""
@pytest.fixture
def sample_text_content(self):
"""Sample text content for testing."""
return TextContent(text="Hello, world!", language="en")
@pytest.fixture
def sample_translated_text(self):
"""Sample translated text content for testing."""
return TextContent(text="Hola, mundo!", language="es")
@pytest.fixture
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