161 lines
7.3 KiB
Python
161 lines
7.3 KiB
Python
import pytest
|
|
from unittest.mock import MagicMock, AsyncMock, patch
|
|
from app.core.redis.redis_manager import RedisManager
|
|
from app.shared.progress import Process
|
|
|
|
class TestMovieMakerAPI:
|
|
"""MovieMaker 관련 API 테스트"""
|
|
|
|
@patch('app.workers.tasks.task1_crawl.s')
|
|
@patch('app.workers.tasks.task2_generate_lyrics.s')
|
|
@patch('app.workers.tasks.task3_generate_music.s')
|
|
@patch('app.workers.tasks.task1_crawl_images.s')
|
|
@patch('app.workers.tasks.task4_generate_video.s')
|
|
@patch('app.workers.tasks.task5_merge_results.s')
|
|
def test_start_workflow_success(self, mock_merge, mock_video, mock_images,
|
|
mock_music, mock_lyrics, mock_crawl,
|
|
client, mock_redis_manager):
|
|
"""워크플로우 시작 성공 테스트"""
|
|
# Mock 설정
|
|
with patch('app.presentation.api.v1.moviemakers.RedisManager', return_value=mock_redis_manager):
|
|
with patch('app.presentation.api.v1.moviemakers.Process') as mock_process_class:
|
|
# Process 인스턴스 mock
|
|
mock_process_instance = MagicMock()
|
|
mock_process_instance.init_task_status = AsyncMock(return_value=None)
|
|
mock_process_class.return_value = mock_process_instance
|
|
|
|
# Celery task mocks
|
|
mock_workflow = MagicMock()
|
|
mock_workflow.apply_async.return_value = MagicMock(id="celery_task_123")
|
|
|
|
# 각 task의 signature mock
|
|
for mock_task in [mock_crawl, mock_lyrics, mock_music, mock_images, mock_video, mock_merge]:
|
|
mock_task.return_value = MagicMock()
|
|
|
|
# 테스트 실행
|
|
response = client.post("/api/v1/moviemaker/start-workflow", json={
|
|
"url": "https://example.com/test"
|
|
})
|
|
|
|
# 검증
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "task_id" in data
|
|
assert data["progress"]["metadata"] == False
|
|
assert data["progress"]["lyrics"] == False
|
|
assert data["progress"]["songs"] == False
|
|
assert data["progress"]["images"] == False
|
|
assert data["progress"]["movies"] == False
|
|
assert data["progress"]["combined"] == False
|
|
|
|
def test_start_workflow_invalid_url(self, client):
|
|
"""잘못된 URL로 워크플로우 시작 테스트"""
|
|
response = client.post("/api/v1/moviemaker/start-workflow", json={
|
|
"url": "not-a-valid-url"
|
|
})
|
|
|
|
# URL 유효성 검사가 없다면 정상적으로 처리됨
|
|
assert response.status_code == 200
|
|
|
|
def test_start_workflow_empty_url(self, client):
|
|
"""빈 URL로 워크플로우 시작 테스트"""
|
|
response = client.post("/api/v1/moviemaker/start-workflow", json={
|
|
"url": ""
|
|
})
|
|
|
|
# 빈 문자열도 처리됨
|
|
assert response.status_code == 200
|
|
|
|
def test_get_progress_success(self, client, mock_redis_manager):
|
|
"""진행상황 조회 성공 테스트"""
|
|
# Mock 설정
|
|
with patch('app.presentation.api.v1.moviemakers.RedisManager', return_value=mock_redis_manager):
|
|
with patch('app.presentation.api.v1.moviemakers.Process') as mock_process_class:
|
|
# Process 인스턴스 mock
|
|
mock_process_instance = MagicMock()
|
|
mock_process_instance.get_task_status = AsyncMock(return_value={
|
|
"metadata": True,
|
|
"lyrics": True,
|
|
"songs": True,
|
|
"images": False,
|
|
"movies": False,
|
|
"combined": False
|
|
})
|
|
mock_process_class.return_value = mock_process_instance
|
|
|
|
# 테스트 실행
|
|
response = client.post("/api/v1/moviemaker/progress", json={
|
|
"task_id": "test_task_123"
|
|
})
|
|
|
|
# 검증
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["progress"]["metadata"] == True
|
|
assert data["progress"]["lyrics"] == True
|
|
assert data["progress"]["songs"] == True
|
|
assert data["progress"]["images"] == False
|
|
|
|
def test_get_progress_not_found(self, client, mock_redis_manager):
|
|
"""존재하지 않는 task_id로 진행상황 조회 테스트"""
|
|
# Mock 설정
|
|
with patch('app.presentation.api.v1.moviemakers.RedisManager', return_value=mock_redis_manager):
|
|
with patch('app.presentation.api.v1.moviemakers.Process') as mock_process_class:
|
|
# Process 인스턴스 mock
|
|
mock_process_instance = MagicMock()
|
|
mock_process_instance.get_task_status = AsyncMock(return_value=None)
|
|
mock_process_class.return_value = mock_process_instance
|
|
|
|
# 테스트 실행
|
|
response = client.post("/api/v1/moviemaker/progress", json={
|
|
"task_id": "non_existent_task"
|
|
})
|
|
|
|
# 검증
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["progress"] is None
|
|
|
|
def test_get_progress_completed(self, client, mock_redis_manager):
|
|
"""완료된 작업의 진행상황 조회 테스트"""
|
|
# Mock 설정
|
|
with patch('app.presentation.api.v1.moviemakers.RedisManager', return_value=mock_redis_manager):
|
|
with patch('app.presentation.api.v1.moviemakers.Process') as mock_process_class:
|
|
# Process 인스턴스 mock
|
|
mock_process_instance = MagicMock()
|
|
mock_process_instance.get_task_status = AsyncMock(return_value={
|
|
"metadata": True,
|
|
"lyrics": True,
|
|
"songs": True,
|
|
"images": True,
|
|
"movies": True,
|
|
"combined": True
|
|
})
|
|
mock_process_class.return_value = mock_process_instance
|
|
|
|
# 테스트 실행
|
|
response = client.post("/api/v1/moviemaker/progress", json={
|
|
"task_id": "completed_task_123"
|
|
})
|
|
|
|
# 검증
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
# 모든 단계가 완료됨
|
|
for key in ["metadata", "lyrics", "songs", "images", "movies", "combined"]:
|
|
assert data["progress"][key] == True
|
|
|
|
@patch('app.presentation.api.v1.moviemakers.RedisManager')
|
|
def test_workflow_redis_error(self, mock_redis_class, client):
|
|
"""Redis 연결 오류 시 워크플로우 테스트"""
|
|
# Redis 연결 실패 시뮬레이션
|
|
mock_redis_class.side_effect = Exception("Redis connection failed")
|
|
|
|
# 테스트 실행
|
|
response = client.post("/api/v1/moviemaker/start-workflow", json={
|
|
"url": "https://example.com/test"
|
|
})
|
|
|
|
# 검증 - 에러가 발생하면 500 에러
|
|
assert response.status_code == 500
|