diff --git a/backend/app/test/test_integration_phase2.py b/backend/app/test/test_integration_phase2.py index dab6714..271f428 100644 --- a/backend/app/test/test_integration_phase2.py +++ b/backend/app/test/test_integration_phase2.py @@ -27,6 +27,7 @@ def video_client(tmp_path, monkeypatch): upload_dir.mkdir() monkeypatch.setenv("VIDEO_UPLOAD_DIR", str(upload_dir)) monkeypatch.setenv("MAX_VIDEO_SIZE_MB", "50") + monkeypatch.setenv("ASR_PROVIDER", "dashscope") monkeypatch.setenv("DASHSCOPE_API_KEY", "sk-test-key") from app.core.config import get_settings @@ -49,7 +50,7 @@ def _upload_video(client, filename="test.mp4", content=b"\x00" * 1024): class TestUploadTranscribeFlow: """Full upload → transcribe with mocked ASR and real file I/O.""" - @patch("app.services.asr_client.OpenAI") + @patch("app.services.asr_providers.OpenAI") @patch("app.services.video_service.asyncio.create_subprocess_exec") def test_upload_then_transcribe(self, mock_subprocess, mock_openai_cls, video_client): """Upload video → extract audio (mocked ffmpeg) → transcribe (mocked ASR) → verify response.""" @@ -93,7 +94,7 @@ class TestUploadTranscribeFlow: wav_path = upload_dir / f"{video_id}_audio.wav" assert not wav_path.exists(), "Temp WAV file should be cleaned up after transcription" - @patch("app.services.asr_client.OpenAI") + @patch("app.services.asr_providers.OpenAI") @patch("app.services.video_service.asyncio.create_subprocess_exec") def test_upload_transcribe_custom_language(self, mock_subprocess, mock_openai_cls, video_client): """Transcribe with language=en should pass it through.""" diff --git a/backend/app/test/test_phase2_asr_client.py b/backend/app/test/test_phase2_asr_client.py index ef8721b..8eb7ff8 100644 --- a/backend/app/test/test_phase2_asr_client.py +++ b/backend/app/test/test_phase2_asr_client.py @@ -123,10 +123,12 @@ class TestToTraditional: class TestTranscribeFull: - def test_returns_traditional_chinese_text(self, monkeypatch): + @pytest.mark.asyncio + async def test_returns_traditional_chinese_text(self, monkeypatch): from app.services.asr_client import ASRClient settings = MagicMock() + settings.asr_provider = "dashscope" settings.dashscope_api_key = "sk-test-key" settings.asr_model_name = "qwen3-asr-flash" @@ -139,8 +141,8 @@ class TestTranscribeFull: mock_openai_client = MagicMock() mock_openai_client.chat.completions.create.return_value = mock_resp - with patch("app.services.asr_client.OpenAI", return_value=mock_openai_client): - result = client.transcribe_full(b"fake-audio-bytes", language="yue") + with patch("app.services.asr_providers.OpenAI", return_value=mock_openai_client): + result = await client.transcribe_full(b"fake-audio-bytes", language="yue") assert result == "測試結果" mock_openai_client.chat.completions.create.assert_called_once() @@ -148,10 +150,12 @@ class TestTranscribeFull: assert call_kwargs.kwargs["model"] == "qwen3-asr-flash" assert call_kwargs.kwargs["extra_body"]["asr_options"]["language"] == "yue" - def test_uses_correct_api_endpoint(self, monkeypatch): + @pytest.mark.asyncio + async def test_uses_correct_api_endpoint(self, monkeypatch): from app.services.asr_client import ASRClient settings = MagicMock() + settings.asr_provider = "dashscope" settings.dashscope_api_key = "sk-test-key" settings.asr_model_name = "qwen3-asr-flash" @@ -164,17 +168,19 @@ class TestTranscribeFull: mock_openai_client = MagicMock() mock_openai_client.chat.completions.create.return_value = mock_resp - with patch("app.services.asr_client.OpenAI", return_value=mock_openai_client) as mock_openai_cls: - client.transcribe_full(b"audio", language="yue") + with patch("app.services.asr_providers.OpenAI", return_value=mock_openai_client) as mock_openai_cls: + await client.transcribe_full(b"audio", language="yue") mock_openai_cls.assert_called_once_with( api_key="sk-test-key", base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1", ) - def test_auto_language_omits_language_param(self, monkeypatch): + @pytest.mark.asyncio + async def test_auto_language_omits_language_param(self, monkeypatch): from app.services.asr_client import ASRClient settings = MagicMock() + settings.asr_provider = "dashscope" settings.dashscope_api_key = "sk-test-key" settings.asr_model_name = "qwen3-asr-flash" @@ -187,8 +193,8 @@ class TestTranscribeFull: mock_openai_client = MagicMock() mock_openai_client.chat.completions.create.return_value = mock_resp - with patch("app.services.asr_client.OpenAI", return_value=mock_openai_client): - client.transcribe_full(b"audio", language="auto") + with patch("app.services.asr_providers.OpenAI", return_value=mock_openai_client): + await client.transcribe_full(b"audio", language="auto") call_kwargs = mock_openai_client.chat.completions.create.call_args assert call_kwargs.kwargs.get("extra_body") is None diff --git a/backend/app/test/test_phase2_full_transcript.py b/backend/app/test/test_phase2_full_transcript.py index c69a06c..c0f8106 100644 --- a/backend/app/test/test_phase2_full_transcript.py +++ b/backend/app/test/test_phase2_full_transcript.py @@ -23,6 +23,7 @@ def video_client(tmp_path, monkeypatch): upload_dir.mkdir() monkeypatch.setenv("VIDEO_UPLOAD_DIR", str(upload_dir)) monkeypatch.setenv("MAX_VIDEO_SIZE_MB", "50") + monkeypatch.setenv("ASR_PROVIDER", "dashscope") monkeypatch.setenv("DASHSCOPE_API_KEY", "sk-test-key") from app.core.config import get_settings @@ -44,7 +45,7 @@ def _upload_video(client, filename="test.mp4", content=b"\x00" * 1024): class TestTranscribeSuccess: @patch("app.routers.video.VideoService.extract_audio") - @patch("app.services.asr_client.OpenAI") + @patch("app.services.asr_providers.OpenAI") def test_transcribe_returns_response(self, mock_openai_cls, mock_extract, video_client): """POST transcribe should return FullTranscriptResponse.""" client, upload_dir = video_client @@ -74,7 +75,7 @@ class TestTranscribeSuccess: assert "測" in data["text"] or "試" in data["text"] @patch("app.routers.video.VideoService.extract_audio") - @patch("app.services.asr_client.OpenAI") + @patch("app.services.asr_providers.OpenAI") def test_transcribe_custom_language(self, mock_openai_cls, mock_extract, video_client): """POST transcribe with language param should pass it through.""" client, upload_dir = video_client @@ -169,6 +170,7 @@ class TestTranscribeMissingApiKey: upload_dir.mkdir() monkeypatch.setenv("VIDEO_UPLOAD_DIR", str(upload_dir)) monkeypatch.setenv("MAX_VIDEO_SIZE_MB", "50") + monkeypatch.setenv("ASR_PROVIDER", "dashscope") monkeypatch.setenv("DASHSCOPE_API_KEY", "") from app.core.config import get_settings