teachingAssistant / tests /unit /domain /models /test_audio_content.py
Michael Hu
refactor based on DDD
5009cb8
"""Unit tests for AudioContent value object."""
import pytest
from src.domain.models.audio_content import AudioContent
class TestAudioContent:
"""Test cases for AudioContent value object."""
def test_valid_audio_content_creation(self):
"""Test creating valid AudioContent instance."""
audio_data = b"fake_audio_data"
audio = AudioContent(
data=audio_data,
format="wav",
sample_rate=44100,
duration=10.5,
filename="test.wav"
)
assert audio.data == audio_data
assert audio.format == "wav"
assert audio.sample_rate == 44100
assert audio.duration == 10.5
assert audio.filename == "test.wav"
assert audio.size_bytes == len(audio_data)
assert audio.is_valid_format is True
def test_audio_content_without_filename(self):
"""Test creating AudioContent without filename."""
audio = AudioContent(
data=b"fake_audio_data",
format="mp3",
sample_rate=22050,
duration=5.0
)
assert audio.filename is None
assert audio.format == "mp3"
def test_empty_audio_data_raises_error(self):
"""Test that empty audio data raises ValueError."""
with pytest.raises(ValueError, match="Audio data cannot be empty"):
AudioContent(
data=b"",
format="wav",
sample_rate=44100,
duration=10.0
)
def test_non_bytes_audio_data_raises_error(self):
"""Test that non-bytes audio data raises TypeError."""
with pytest.raises(TypeError, match="Audio data must be bytes"):
AudioContent(
data="not_bytes", # type: ignore
format="wav",
sample_rate=44100,
duration=10.0
)
def test_unsupported_format_raises_error(self):
"""Test that unsupported format raises ValueError."""
with pytest.raises(ValueError, match="Unsupported audio format: xyz"):
AudioContent(
data=b"fake_audio_data",
format="xyz",
sample_rate=44100,
duration=10.0
)
def test_supported_formats(self):
"""Test all supported audio formats."""
supported_formats = ['wav', 'mp3', 'flac', 'ogg']
for fmt in supported_formats:
audio = AudioContent(
data=b"fake_audio_data",
format=fmt,
sample_rate=44100,
duration=10.0
)
assert audio.format == fmt
assert audio.is_valid_format is True
def test_negative_sample_rate_raises_error(self):
"""Test that negative sample rate raises ValueError."""
with pytest.raises(ValueError, match="Sample rate must be positive"):
AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=-1,
duration=10.0
)
def test_zero_sample_rate_raises_error(self):
"""Test that zero sample rate raises ValueError."""
with pytest.raises(ValueError, match="Sample rate must be positive"):
AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=0,
duration=10.0
)
def test_sample_rate_too_low_raises_error(self):
"""Test that sample rate below 8000 raises ValueError."""
with pytest.raises(ValueError, match="Sample rate must be between 8000 and 192000 Hz"):
AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=7999,
duration=10.0
)
def test_sample_rate_too_high_raises_error(self):
"""Test that sample rate above 192000 raises ValueError."""
with pytest.raises(ValueError, match="Sample rate must be between 8000 and 192000 Hz"):
AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=192001,
duration=10.0
)
def test_valid_sample_rate_boundaries(self):
"""Test valid sample rate boundaries."""
# Test minimum valid sample rate
audio_min = AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=8000,
duration=10.0
)
assert audio_min.sample_rate == 8000
# Test maximum valid sample rate
audio_max = AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=192000,
duration=10.0
)
assert audio_max.sample_rate == 192000
def test_negative_duration_raises_error(self):
"""Test that negative duration raises ValueError."""
with pytest.raises(ValueError, match="Duration must be positive"):
AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=44100,
duration=-1.0
)
def test_zero_duration_raises_error(self):
"""Test that zero duration raises ValueError."""
with pytest.raises(ValueError, match="Duration must be positive"):
AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=44100,
duration=0.0
)
def test_duration_too_long_raises_error(self):
"""Test that duration over 1 hour raises ValueError."""
with pytest.raises(ValueError, match="Audio duration cannot exceed 1 hour"):
AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=44100,
duration=3601.0 # 1 hour + 1 second
)
def test_valid_duration_boundary(self):
"""Test valid duration boundary (exactly 1 hour)."""
audio = AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=44100,
duration=3600.0 # Exactly 1 hour
)
assert audio.duration == 3600.0
def test_empty_filename_raises_error(self):
"""Test that empty filename raises ValueError."""
with pytest.raises(ValueError, match="Filename cannot be empty string"):
AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=44100,
duration=10.0,
filename=""
)
def test_whitespace_filename_raises_error(self):
"""Test that whitespace-only filename raises ValueError."""
with pytest.raises(ValueError, match="Filename cannot be empty string"):
AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=44100,
duration=10.0,
filename=" "
)
def test_audio_content_is_immutable(self):
"""Test that AudioContent is immutable (frozen dataclass)."""
audio = AudioContent(
data=b"fake_audio_data",
format="wav",
sample_rate=44100,
duration=10.0
)
with pytest.raises(AttributeError):
audio.format = "mp3" # type: ignore
def test_size_bytes_property(self):
"""Test size_bytes property returns correct value."""
test_data = b"test_audio_data_123"
audio = AudioContent(
data=test_data,
format="wav",
sample_rate=44100,
duration=10.0
)
assert audio.size_bytes == len(test_data)