Files
web-page-backend/music-lab/tests/test_review.py

85 lines
3.9 KiB
Python

import pytest
import respx
from httpx import Response
from app.pipeline import review
@pytest.mark.asyncio
@respx.mock
async def test_review_returns_pass_when_above_threshold(monkeypatch):
monkeypatch.setenv("ANTHROPIC_API_KEY", "k")
body = {"content": [{"type": "text", "text":
'{"metadata_quality":{"score":80,"notes":"x"},'
'"policy_compliance":{"score":90,"issues":[]},'
'"viewer_experience":{"score":75,"notes":"y"},'
'"trend_alignment":{"score":70,"matched_keywords":["lofi"]},'
'"summary":"good"}'}]}
respx.post("https://api.anthropic.com/v1/messages").mock(return_value=Response(200, json=body))
result = await review.run_4_axis(
pipeline={"id": 1}, track={"title": "x", "genre": "lo-fi", "bpm": 85},
video_meta={"length_sec": 120, "resolution": "1920x1080"},
metadata={"title": "Y", "description": "Z", "tags": ["lofi"], "category_id": 10},
thumbnail_url="/m/x.jpg", trend_top=["lofi"],
weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
threshold=60,
)
assert result["verdict"] == "pass"
expected_total = 0.25 * 80 + 0.30 * 90 + 0.25 * 75 + 0.20 * 70
assert result["weighted_total"] == pytest.approx(expected_total, abs=0.01)
@pytest.mark.asyncio
@respx.mock
async def test_review_fail_below_threshold(monkeypatch):
monkeypatch.setenv("ANTHROPIC_API_KEY", "k")
body = {"content": [{"type": "text", "text":
'{"metadata_quality":{"score":40,"notes":"x"},'
'"policy_compliance":{"score":50,"issues":[]},'
'"viewer_experience":{"score":30,"notes":"y"},'
'"trend_alignment":{"score":20,"matched_keywords":[]},'
'"summary":"bad"}'}]}
respx.post("https://api.anthropic.com/v1/messages").mock(return_value=Response(200, json=body))
result = await review.run_4_axis(
pipeline={"id": 2}, track={"title": "x", "genre": "lo-fi", "bpm": 85},
video_meta={"length_sec": 120, "resolution": "1920x1080"},
metadata={"title": "Y", "description": "Z", "tags": [], "category_id": 10},
thumbnail_url="/m/x.jpg", trend_top=[],
weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
threshold=60,
)
assert result["verdict"] == "fail"
@pytest.mark.asyncio
@respx.mock
async def test_review_heuristic_fallback_on_llm_error(monkeypatch):
monkeypatch.setenv("ANTHROPIC_API_KEY", "k")
respx.post("https://api.anthropic.com/v1/messages").mock(return_value=Response(500))
result = await review.run_4_axis(
pipeline={"id": 3}, track={"title": "x", "genre": "lo-fi", "bpm": 85, "duration_sec": 120},
video_meta={"length_sec": 120, "resolution": "1920x1080"},
metadata={"title": "Y" * 30, "description": "Z" * 200, "tags": ["a", "b", "c", "d", "e"], "category_id": 10},
thumbnail_url="/m/x.jpg", trend_top=["lofi"],
weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
threshold=60,
)
assert result["used_fallback"] is True
assert "weighted_total" in result
@pytest.mark.asyncio
async def test_review_heuristic_when_no_api_key(monkeypatch):
monkeypatch.delenv("ANTHROPIC_API_KEY", raising=False)
result = await review.run_4_axis(
pipeline={"id": 4}, track={"title": "x", "genre": "lo-fi", "bpm": 85, "duration_sec": 120},
video_meta={"length_sec": 120, "resolution": "1920x1080"},
metadata={"title": "Test Title", "description": "Description here, more text " * 5,
"tags": ["lofi", "study", "chill", "ambient", "instrumental"], "category_id": 10},
thumbnail_url="/m/x.jpg", trend_top=["lofi"],
weights={"meta": 25, "policy": 30, "viewer": 25, "trend": 20},
threshold=60,
)
assert result["used_fallback"] is True
# 휴리스틱: 좋은 메타+영상길이 일치+태그 트렌드 겹침 → pass 기대
assert result["verdict"] == "pass"