a75fa1cd93
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 40s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 59s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m41s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m16s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 5m16s
CI/CD Pipeline / Validate - Code Quality (push) Successful in 5m24s
CI/CD Pipeline / Integration Tests (push) Successful in 1m21s
CI/CD Pipeline / Unit Tests (push) Successful in 8m50s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 12m12s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m25s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 38s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m13s
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m29s
152 lines
5.8 KiB
Python
152 lines
5.8 KiB
Python
"""Tests for voice_ids fallback in _download_all_assets.
|
|
|
|
When voice_library_id is empty but voice_ids is non-empty, the Worker
|
|
should fallback to voice_ids[0] as the audio asset_id.
|
|
"""
|
|
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
|
|
class TestDownloadAllAssetsVoiceIdsFallback:
|
|
"""_download_all_assets 配音下载 fallback 逻辑测试。"""
|
|
|
|
@patch("worker_app.tasks.generation._download_voice_asset")
|
|
@patch("worker_app.tasks.generation._download_library_assets")
|
|
def test_voice_library_id_takes_priority(self, mock_download_videos, mock_download_voice, tmp_path):
|
|
"""voice_library_id 存在时优先使用,不 fallback 到 voice_ids。"""
|
|
from worker_app.tasks.generation import _download_all_assets
|
|
|
|
mock_download_videos.return_value = [tmp_path / "v1.mp4"]
|
|
mock_download_voice.return_value = True
|
|
|
|
videos, audio = _download_all_assets(
|
|
temp_path=tmp_path,
|
|
asset_library_id="lib-1",
|
|
project_id="proj-1",
|
|
task_asset_ids=["a1"],
|
|
voice_library_id="voice-lib-123",
|
|
task_id="task-1",
|
|
voice_ids=["voice-ids-456"],
|
|
)
|
|
|
|
assert audio is not None
|
|
mock_download_voice.assert_called_once()
|
|
call_args = mock_download_voice.call_args
|
|
assert call_args[0][0] == "voice-lib-123" # first positional arg
|
|
|
|
@patch("worker_app.tasks.generation._download_voice_asset")
|
|
@patch("worker_app.tasks.generation._download_library_assets")
|
|
def test_fallback_to_voice_ids_when_voice_library_id_empty(
|
|
self, mock_download_videos, mock_download_voice, tmp_path
|
|
):
|
|
"""voice_library_id 为空时 fallback 到 voice_ids[0]。"""
|
|
from worker_app.tasks.generation import _download_all_assets
|
|
|
|
mock_download_videos.return_value = [tmp_path / "v1.mp4"]
|
|
mock_download_voice.return_value = True
|
|
|
|
videos, audio = _download_all_assets(
|
|
temp_path=tmp_path,
|
|
asset_library_id="lib-1",
|
|
project_id="proj-1",
|
|
task_asset_ids=["a1"],
|
|
voice_library_id="", # 空字符串
|
|
task_id="task-2",
|
|
voice_ids=["voice-asset-789"],
|
|
)
|
|
|
|
assert audio is not None
|
|
mock_download_voice.assert_called_once()
|
|
call_args = mock_download_voice.call_args
|
|
assert call_args[0][0] == "voice-asset-789"
|
|
|
|
@patch("worker_app.tasks.generation._download_voice_asset")
|
|
@patch("worker_app.tasks.generation._download_library_assets")
|
|
def test_no_audio_when_both_empty(self, mock_download_videos, mock_download_voice, tmp_path):
|
|
"""voice_library_id 和 voice_ids 都为空时,不下载音频。"""
|
|
from worker_app.tasks.generation import _download_all_assets
|
|
|
|
mock_download_videos.return_value = [tmp_path / "v1.mp4"]
|
|
|
|
videos, audio = _download_all_assets(
|
|
temp_path=tmp_path,
|
|
asset_library_id="lib-1",
|
|
project_id="proj-1",
|
|
task_asset_ids=["a1"],
|
|
voice_library_id="",
|
|
task_id="task-3",
|
|
voice_ids=[],
|
|
)
|
|
|
|
assert audio is None
|
|
mock_download_voice.assert_not_called()
|
|
|
|
@patch("worker_app.tasks.generation._download_voice_asset")
|
|
@patch("worker_app.tasks.generation._download_library_assets")
|
|
def test_no_audio_when_voice_ids_none(self, mock_download_videos, mock_download_voice, tmp_path):
|
|
"""voice_ids 为 None 时,不触发 fallback。"""
|
|
from worker_app.tasks.generation import _download_all_assets
|
|
|
|
mock_download_videos.return_value = [tmp_path / "v1.mp4"]
|
|
|
|
videos, audio = _download_all_assets(
|
|
temp_path=tmp_path,
|
|
asset_library_id="lib-1",
|
|
project_id="proj-1",
|
|
task_asset_ids=["a1"],
|
|
voice_library_id="",
|
|
task_id="task-4",
|
|
voice_ids=None,
|
|
)
|
|
|
|
assert audio is None
|
|
mock_download_voice.assert_not_called()
|
|
|
|
@patch("worker_app.tasks.generation._download_voice_asset")
|
|
@patch("worker_app.tasks.generation._download_library_assets")
|
|
def test_voice_library_id_empty_string_fallback(self, mock_download_videos, mock_download_voice, tmp_path):
|
|
"""voice_library_id 为空字符串且 voice_ids 有多个元素时,取第一个。"""
|
|
from worker_app.tasks.generation import _download_all_assets
|
|
|
|
mock_download_videos.return_value = [tmp_path / "v1.mp4"]
|
|
mock_download_voice.return_value = True
|
|
|
|
videos, audio = _download_all_assets(
|
|
temp_path=tmp_path,
|
|
asset_library_id="lib-1",
|
|
project_id="proj-1",
|
|
task_asset_ids=["a1"],
|
|
voice_library_id="",
|
|
task_id="task-5",
|
|
voice_ids=["first-id", "second-id", "third-id"],
|
|
)
|
|
|
|
assert audio is not None
|
|
call_args = mock_download_voice.call_args
|
|
assert call_args[0][0] == "first-id"
|
|
|
|
@patch("worker_app.tasks.generation._download_voice_asset")
|
|
@patch("worker_app.tasks.generation._download_library_assets")
|
|
def test_backward_compat_no_voice_ids_param(self, mock_download_videos, mock_download_voice, tmp_path):
|
|
"""不传 voice_ids 参数时,行为与之前一致(向后兼容)。"""
|
|
from worker_app.tasks.generation import _download_all_assets
|
|
|
|
mock_download_videos.return_value = [tmp_path / "v1.mp4"]
|
|
mock_download_voice.return_value = True
|
|
|
|
# 不传 voice_ids
|
|
videos, audio = _download_all_assets(
|
|
temp_path=tmp_path,
|
|
asset_library_id="lib-1",
|
|
project_id="proj-1",
|
|
task_asset_ids=["a1"],
|
|
voice_library_id="voice-lib-999",
|
|
task_id="task-6",
|
|
)
|
|
|
|
assert audio is not None
|
|
mock_download_voice.assert_called_once_with("voice-lib-999", tmp_path / "voice.mp3")
|