atsushieee's picture
Upload folder using huggingface_hub
d53fa1b verified
from unittest.mock import Mock, patch
import numpy as np
import pytest
from improvisation_lab.application.interval_practice.web_interval_app import \
WebIntervalPracticeApp
from improvisation_lab.config import Config
from improvisation_lab.domain.music_theory import Notes
from improvisation_lab.infrastructure.audio import WebAudioProcessor
from improvisation_lab.presentation.interval_practice.web_interval_view import \
WebIntervalPracticeView
from improvisation_lab.service import IntervalPracticeService
class TestWebIntervalPracticeApp:
@pytest.fixture
def init_module(self):
"""Initialize WebIntervalPracticeApp for testing."""
config = Config()
service = IntervalPracticeService(config)
self.app = WebIntervalPracticeApp(service, config)
self.app.ui = Mock(spec=WebIntervalPracticeView)
self.app.audio_processor = Mock(spec=WebAudioProcessor)
@pytest.mark.usefixtures("init_module")
def test_launch(self):
"""Test launching the application."""
with patch.object(self.app.ui, "launch", return_value=None) as mock_launch:
self.app.launch()
mock_launch.assert_called_once()
@pytest.mark.usefixtures("init_module")
def test_process_audio_callback(self):
"""Test processing audio callback."""
audio_data = np.array([0.0])
self.app.is_running = True
self.app.phrases = [
[Notes.C, Notes.C_SHARP, Notes.C],
[Notes.D, Notes.D_SHARP, Notes.D],
]
self.app.current_phrase_idx = 0
self.app.current_note_idx = 1
mock_result = Mock()
mock_result.target_note = "C#"
mock_result.current_base_note = "C#"
mock_result.remaining_time = 0.0
with patch.object(
self.app.service, "process_audio", return_value=mock_result
) as mock_process_audio:
self.app._process_audio_callback(audio_data)
mock_process_audio.assert_called_once_with(audio_data, "C#")
assert (
self.app.text_manager.result_text
== "Target: C# | Your note: C# | Remaining: 0.0s"
)
@pytest.mark.usefixtures("init_module")
def test_handle_audio(self):
"""Test handling audio input."""
audio_data = (48000, np.array([0.0]))
self.app.is_running = True
with patch.object(
self.app.audio_processor, "process_audio", return_value=None
) as mock_process_audio:
base_note, phrase_text, result_text, results_table = self.app.handle_audio(
audio_data
)
mock_process_audio.assert_called_once_with(audio_data)
assert base_note == self.app.base_note
assert phrase_text == self.app.text_manager.phrase_text
assert result_text == self.app.text_manager.result_text
assert results_table == self.app.results_table
@pytest.mark.usefixtures("init_module")
def test_start(self):
"""Test starting the application."""
self.app.audio_processor.is_recording = False
with patch.object(
self.app.audio_processor, "start_recording", return_value=None
) as mock_start_recording:
base_note, phrase_text, result_text, results_table = self.app.start(
"minor 2nd", "Up", 10, True, 1.5
)
mock_start_recording.assert_called_once()
assert self.app.is_running
assert base_note == self.app.base_note
assert phrase_text == self.app.text_manager.phrase_text
assert result_text == self.app.text_manager.result_text
assert results_table == self.app.results_table
@pytest.mark.usefixtures("init_module")
def test_stop(self):
"""Test stopping the application."""
self.app.audio_processor.is_recording = True
with patch.object(
self.app.audio_processor, "stop_recording", return_value=None
) as mock_stop_recording:
base_note, phrase_text, result_text = self.app.stop()
mock_stop_recording.assert_called_once()
assert not self.app.is_running
assert base_note == "-"
assert phrase_text == self.app.text_manager.phrase_text
assert result_text == self.app.text_manager.result_text
@pytest.mark.usefixtures("init_module")
@pytest.mark.parametrize(
"detected_note, expected_result",
[("C#", "⭕️"), ("D", "X")], # Correct case # Incorrect case
)
def test_update_results_table(self, detected_note, expected_result):
"""Test updating the results table with correct and incorrect results."""
self.app.phrases = [[Notes.C, Notes.C_SHARP, Notes.C]]
self.app.current_phrase_idx = 0
self.app.current_note_idx = 1
self.app.base_note = "C"
self.app.text_manager.result_text = f"Target: C# | Your note: {detected_note}"
self.app.is_auto_advance = True
self.app.update_results_table()
expected_entry = [1, "C", "C#", detected_note, expected_result]
assert self.app.results_table[-1] == expected_entry