teachingAssistant / tests /unit /application /dtos /test_processing_result_dto.py
Michael Hu
Create unit tests for application layer
acd758a
"""Unit tests for ProcessingResultDto"""
import pytest
from datetime import datetime
from src.application.dtos.processing_result_dto import ProcessingResultDto
class TestProcessingResultDto:
"""Test cases for ProcessingResultDto"""
def test_valid_success_processing_result_dto(self):
"""Test creating a valid successful ProcessingResultDto"""
dto = ProcessingResultDto(
success=True,
original_text="Hello world",
translated_text="Hola mundo",
audio_path="/tmp/output.wav",
processing_time=5.2,
metadata={"correlation_id": "test-123"}
)
assert dto.success is True
assert dto.original_text == "Hello world"
assert dto.translated_text == "Hola mundo"
assert dto.audio_path == "/tmp/output.wav"
assert dto.processing_time == 5.2
assert dto.metadata == {"correlation_id": "test-123"}
assert dto.error_message is None
assert dto.error_code is None
assert isinstance(dto.timestamp, datetime)
def test_valid_error_processing_result_dto(self):
"""Test creating a valid error ProcessingResultDto"""
dto = ProcessingResultDto(
success=False,
error_message="Processing failed",
error_code="STT_ERROR",
processing_time=2.1,
metadata={"correlation_id": "test-456"}
)
assert dto.success is False
assert dto.error_message == "Processing failed"
assert dto.error_code == "STT_ERROR"
assert dto.processing_time == 2.1
assert dto.metadata == {"correlation_id": "test-456"}
assert dto.original_text is None
assert dto.translated_text is None
assert dto.audio_path is None
assert isinstance(dto.timestamp, datetime)
def test_processing_result_dto_with_defaults(self):
"""Test creating ProcessingResultDto with default values"""
dto = ProcessingResultDto(success=True, original_text="Test")
assert dto.success is True
assert dto.original_text == "Test"
assert dto.translated_text is None
assert dto.audio_path is None
assert dto.processing_time == 0.0
assert dto.error_message is None
assert dto.error_code is None
assert dto.metadata == {}
assert isinstance(dto.timestamp, datetime)
def test_processing_result_dto_with_explicit_timestamp(self):
"""Test creating ProcessingResultDto with explicit timestamp"""
test_timestamp = datetime(2023, 1, 1, 12, 0, 0)
dto = ProcessingResultDto(
success=True,
original_text="Test",
timestamp=test_timestamp
)
assert dto.timestamp == test_timestamp
def test_invalid_success_type_validation(self):
"""Test validation with invalid success type"""
with pytest.raises(ValueError, match="Success must be a boolean value"):
ProcessingResultDto(
success="true", # String instead of boolean
original_text="Test"
)
def test_negative_processing_time_validation(self):
"""Test validation with negative processing time"""
with pytest.raises(ValueError, match="Processing time cannot be negative"):
ProcessingResultDto(
success=True,
original_text="Test",
processing_time=-1.0
)
def test_successful_processing_without_output_validation(self):
"""Test validation for successful processing without any output"""
with pytest.raises(ValueError, match="Successful processing must have at least one output"):
ProcessingResultDto(
success=True,
# No original_text, translated_text, or audio_path
)
def test_failed_processing_without_error_message_validation(self):
"""Test validation for failed processing without error message"""
with pytest.raises(ValueError, match="Failed processing must include an error message"):
ProcessingResultDto(
success=False,
# No error_message
)
def test_invalid_error_code_validation(self):
"""Test validation with invalid error code"""
with pytest.raises(ValueError, match="Invalid error code"):
ProcessingResultDto(
success=False,
error_message="Test error",
error_code="INVALID_CODE"
)
def test_valid_error_codes(self):
"""Test all valid error codes"""
valid_error_codes = [
'STT_ERROR', 'TRANSLATION_ERROR', 'TTS_ERROR',
'AUDIO_FORMAT_ERROR', 'VALIDATION_ERROR', 'SYSTEM_ERROR'
]
for error_code in valid_error_codes:
# Should not raise exception
dto = ProcessingResultDto(
success=False,
error_message="Test error",
error_code=error_code
)
assert dto.error_code == error_code
def test_invalid_metadata_type_validation(self):
"""Test validation with invalid metadata type"""
with pytest.raises(ValueError, match="Metadata must be a dictionary"):
ProcessingResultDto(
success=True,
original_text="Test",
metadata="invalid" # String instead of dict
)
def test_has_text_output_property(self):
"""Test has_text_output property"""
# With original text only
dto1 = ProcessingResultDto(success=True, original_text="Test")
assert dto1.has_text_output is True
# With translated text only
dto2 = ProcessingResultDto(success=True, translated_text="Prueba")
assert dto2.has_text_output is True
# With both texts
dto3 = ProcessingResultDto(success=True, original_text="Test", translated_text="Prueba")
assert dto3.has_text_output is True
# With no text
dto4 = ProcessingResultDto(success=True, audio_path="/tmp/test.wav")
assert dto4.has_text_output is False
def test_has_audio_output_property(self):
"""Test has_audio_output property"""
# With audio path
dto1 = ProcessingResultDto(success=True, audio_path="/tmp/test.wav")
assert dto1.has_audio_output is True
# Without audio path
dto2 = ProcessingResultDto(success=True, original_text="Test")
assert dto2.has_audio_output is False
def test_is_complete_property(self):
"""Test is_complete property"""
# Successful processing
dto1 = ProcessingResultDto(success=True, original_text="Test")
assert dto1.is_complete is True
# Failed processing with error message
dto2 = ProcessingResultDto(success=False, error_message="Error")
assert dto2.is_complete is True
# This shouldn't happen due to validation, but test the logic
dto3 = ProcessingResultDto.__new__(ProcessingResultDto)
dto3.success = False
dto3.error_message = None
assert dto3.is_complete is False
def test_add_metadata_method(self):
"""Test add_metadata method"""
dto = ProcessingResultDto(success=True, original_text="Test")
dto.add_metadata("key1", "value1")
dto.add_metadata("key2", 123)
assert dto.metadata["key1"] == "value1"
assert dto.metadata["key2"] == 123
def test_add_metadata_method_with_none_metadata(self):
"""Test add_metadata method when metadata is None"""
dto = ProcessingResultDto.__new__(ProcessingResultDto)
dto.success = True
dto.original_text = "Test"
dto.metadata = None
dto.add_metadata("key", "value")
assert dto.metadata == {"key": "value"}
def test_get_metadata_method(self):
"""Test get_metadata method"""
dto = ProcessingResultDto(
success=True,
original_text="Test",
metadata={"existing_key": "existing_value"}
)
# Get existing key
assert dto.get_metadata("existing_key") == "existing_value"
# Get non-existing key with default
assert dto.get_metadata("non_existing", "default") == "default"
# Get non-existing key without default
assert dto.get_metadata("non_existing") is None
def test_get_metadata_method_with_none_metadata(self):
"""Test get_metadata method when metadata is None"""
dto = ProcessingResultDto.__new__(ProcessingResultDto)
dto.success = True
dto.original_text = "Test"
dto.metadata = None
assert dto.get_metadata("key", "default") == "default"
assert dto.get_metadata("key") is None
def test_to_dict_method(self):
"""Test to_dict method"""
test_timestamp = datetime(2023, 1, 1, 12, 0, 0)
dto = ProcessingResultDto(
success=True,
original_text="Hello world",
translated_text="Hola mundo",
audio_path="/tmp/output.wav",
processing_time=5.2,
error_message=None,
error_code=None,
metadata={"correlation_id": "test-123"},
timestamp=test_timestamp
)
result = dto.to_dict()
assert result['success'] is True
assert result['original_text'] == "Hello world"
assert result['translated_text'] == "Hola mundo"
assert result['audio_path'] == "/tmp/output.wav"
assert result['processing_time'] == 5.2
assert result['error_message'] is None
assert result['error_code'] is None
assert result['metadata'] == {"correlation_id": "test-123"}
assert result['timestamp'] == test_timestamp.isoformat()
assert result['has_text_output'] is True
assert result['has_audio_output'] is True
assert result['is_complete'] is True
def test_to_dict_method_with_none_timestamp(self):
"""Test to_dict method with None timestamp"""
dto = ProcessingResultDto.__new__(ProcessingResultDto)
dto.success = True
dto.original_text = "Test"
dto.translated_text = None
dto.audio_path = None
dto.processing_time = 0.0
dto.error_message = None
dto.error_code = None
dto.metadata = {}
dto.timestamp = None
result = dto.to_dict()
assert result['timestamp'] is None
def test_success_result_class_method(self):
"""Test success_result class method"""
result = ProcessingResultDto.success_result(
original_text="Hello world",
translated_text="Hola mundo",
audio_path="/tmp/output.wav",
processing_time=3.5,
metadata={"test": "value"}
)
assert isinstance(result, ProcessingResultDto)
assert result.success is True
assert result.original_text == "Hello world"
assert result.translated_text == "Hola mundo"
assert result.audio_path == "/tmp/output.wav"
assert result.processing_time == 3.5
assert result.metadata == {"test": "value"}
assert result.error_message is None
assert result.error_code is None
def test_success_result_class_method_with_defaults(self):
"""Test success_result class method with default values"""
result = ProcessingResultDto.success_result(original_text="Test")
assert result.success is True
assert result.original_text == "Test"
assert result.translated_text is None
assert result.audio_path is None
assert result.processing_time == 0.0
assert result.metadata is None
def test_error_result_class_method(self):
"""Test error_result class method"""
result = ProcessingResultDto.error_result(
error_message="Processing failed",
error_code="STT_ERROR",
processing_time=2.1,
metadata={"correlation_id": "test-456"}
)
assert isinstance(result, ProcessingResultDto)
assert result.success is False
assert result.error_message == "Processing failed"
assert result.error_code == "STT_ERROR"
assert result.processing_time == 2.1
assert result.metadata == {"correlation_id": "test-456"}
assert result.original_text is None
assert result.translated_text is None
assert result.audio_path is None
def test_error_result_class_method_with_defaults(self):
"""Test error_result class method with default values"""
result = ProcessingResultDto.error_result("Test error")
assert result.success is False
assert result.error_message == "Test error"
assert result.error_code is None
assert result.processing_time == 0.0
assert result.metadata is None
def test_from_dict_class_method(self):
"""Test from_dict class method"""
test_timestamp = datetime(2023, 1, 1, 12, 0, 0)
data = {
'success': True,
'original_text': 'Hello world',
'translated_text': 'Hola mundo',
'audio_path': '/tmp/output.wav',
'processing_time': 5.2,
'error_message': None,
'error_code': None,
'metadata': {'correlation_id': 'test-123'},
'timestamp': test_timestamp.isoformat()
}
dto = ProcessingResultDto.from_dict(data)
assert dto.success is True
assert dto.original_text == 'Hello world'
assert dto.translated_text == 'Hola mundo'
assert dto.audio_path == '/tmp/output.wav'
assert dto.processing_time == 5.2
assert dto.error_message is None
assert dto.error_code is None
assert dto.metadata == {'correlation_id': 'test-123'}
assert dto.timestamp == test_timestamp
def test_from_dict_class_method_with_z_timestamp(self):
"""Test from_dict class method with Z-suffixed timestamp"""
data = {
'success': True,
'original_text': 'Test',
'timestamp': '2023-01-01T12:00:00Z'
}
dto = ProcessingResultDto.from_dict(data)
assert dto.timestamp == datetime(2023, 1, 1, 12, 0, 0)
def test_from_dict_class_method_with_defaults(self):
"""Test from_dict class method with default values"""
data = {
'success': True,
'original_text': 'Test'
}
dto = ProcessingResultDto.from_dict(data)
assert dto.success is True
assert dto.original_text == 'Test'
assert dto.translated_text is None
assert dto.audio_path is None
assert dto.processing_time == 0.0
assert dto.error_message is None
assert dto.error_code is None
assert dto.metadata is None
assert dto.timestamp is None
def test_validation_called_on_init(self):
"""Test that validation is called during initialization"""
# This should trigger validation and raise an error
with pytest.raises(ValueError):
ProcessingResultDto(
success="invalid", # Invalid type
original_text="Test"
)
def test_metadata_default_initialization(self):
"""Test that metadata is initialized to empty dict if None"""
dto = ProcessingResultDto(
success=True,
original_text="Test",
metadata=None
)
assert dto.metadata == {}
def test_timestamp_default_initialization(self):
"""Test that timestamp is initialized to current time if None"""
before = datetime.utcnow()
dto = ProcessingResultDto(
success=True,
original_text="Test",
timestamp=None
)
after = datetime.utcnow()
assert before <= dto.timestamp <= after