Files
xiaoxia-saas/tests/unit/test_reverse_engine.py
T
xiaoxia 04bcd2e6f9
CI/CD Pipeline / Check if frontend-only change (push) Has been cancelled
CI/CD Pipeline / Validate - Code Quality (push) Has been cancelled
CI/CD Pipeline / Validate - Type Check (mypy) (push) Has been cancelled
CI/CD Pipeline / Validate - Migration (alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Build Staging API Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
test(P3-1): 第60波 reverse引擎+in-memory素材+task_enqueue单测(+85) (#852)
2026-07-24 22:06:07 +08:00

195 lines
7.1 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""ReverseEngine 单测 — 倒放引擎配置解析 + 滤镜构建."""
from __future__ import annotations
import pytest
from video_processing.reverse_engine import ReverseConfig, ReverseEngine
# ── ReverseConfig.from_dict ────────────────────────────────────────────────
class TestReverseConfigFromDict:
"""ReverseConfig.from_dict 配置解析."""
def test_none_returns_disabled(self):
config = ReverseConfig.from_dict(None)
assert config.enabled is False
assert config.reverse_video is True
assert config.reverse_audio is True
def test_empty_dict_returns_disabled(self):
config = ReverseConfig.from_dict({})
assert config.enabled is False
def test_enabled_false(self):
config = ReverseConfig.from_dict({"enabled": False})
assert config.enabled is False
def test_enabled_true_defaults(self):
"""只传 enabled=Truevideo/audio 默认都开."""
config = ReverseConfig.from_dict({"enabled": True})
assert config.enabled is True
assert config.reverse_video is True
assert config.reverse_audio is True
def test_disable_video_only(self):
config = ReverseConfig.from_dict({
"enabled": True,
"reverse_video": False,
"reverse_audio": True,
})
assert config.enabled is True
assert config.reverse_video is False
assert config.reverse_audio is True
def test_disable_audio_only(self):
config = ReverseConfig.from_dict({
"enabled": True,
"reverse_video": True,
"reverse_audio": False,
})
assert config.enabled is True
assert config.reverse_video is True
assert config.reverse_audio is False
def test_both_disabled(self):
config = ReverseConfig.from_dict({
"enabled": True,
"reverse_video": False,
"reverse_audio": False,
})
assert config.enabled is True
assert config.reverse_video is False
assert config.reverse_audio is False
def test_invalid_type_falls_back_default(self):
"""传入非字典类型(如列表),捕获 TypeError,返回默认配置."""
config = ReverseConfig.from_dict([1, 2, 3]) # type: ignore[arg-type]
assert config.enabled is False
def test_attribute_error_falls_back(self):
"""没有 .get() 方法的对象,捕获 AttributeError,返回默认配置."""
config = ReverseConfig.from_dict(123) # type: ignore[arg-type]
assert config.enabled is False
def test_truthy_values(self):
"""非布尔真值也能被 bool() 转换."""
config = ReverseConfig.from_dict({
"enabled": 1,
"reverse_video": 1,
"reverse_audio": "yes",
})
assert config.enabled is True
assert config.reverse_video is True
assert config.reverse_audio is True
def test_falsy_values(self):
"""非布尔假值也能被 bool() 转换."""
config = ReverseConfig.from_dict({
"enabled": True,
"reverse_video": 0,
"reverse_audio": "",
})
assert config.enabled is True
assert config.reverse_video is False
assert config.reverse_audio is False
# ── ReverseEngine.build_video_filter ───────────────────────────────────────
class TestBuildVideoFilter:
"""ReverseEngine.build_video_filter 视频倒放滤镜构建."""
def test_disabled_returns_empty(self):
config = ReverseConfig(enabled=False)
result = ReverseEngine.build_video_filter(config)
assert result == ""
def test_enabled_but_video_off_returns_empty(self):
config = ReverseConfig(enabled=True, reverse_video=False, reverse_audio=True)
result = ReverseEngine.build_video_filter(config)
assert result == ""
def test_enabled_normal_duration(self):
config = ReverseConfig(enabled=True)
result = ReverseEngine.build_video_filter(config, duration=10.0)
assert result == "reverse"
def test_zero_duration(self):
config = ReverseConfig(enabled=True)
result = ReverseEngine.build_video_filter(config, duration=0.0)
assert result == "reverse"
def test_exactly_max_safe_duration(self):
"""刚好等于上限,允许."""
config = ReverseConfig(enabled=True)
result = ReverseEngine.build_video_filter(
config, duration=ReverseEngine.MAX_SAFE_DURATION
)
assert result == "reverse"
def test_exceeds_max_safe_duration_skips(self):
"""超过上限,跳过倒放,返回空字符串."""
config = ReverseConfig(enabled=True)
result = ReverseEngine.build_video_filter(
config, duration=ReverseEngine.MAX_SAFE_DURATION + 1
)
assert result == ""
def test_negative_duration(self):
"""负时长应该不会触发上限,但仍会正常返回 reverse."""
config = ReverseConfig(enabled=True)
result = ReverseEngine.build_video_filter(config, duration=-5.0)
assert result == "reverse"
# ── ReverseEngine.build_audio_filter ───────────────────────────────────────
class TestBuildAudioFilter:
"""ReverseEngine.build_audio_filter 音频倒放滤镜构建."""
def test_disabled_returns_empty(self):
config = ReverseConfig(enabled=False)
result = ReverseEngine.build_audio_filter(config)
assert result == ""
def test_enabled_but_audio_off_returns_empty(self):
config = ReverseConfig(enabled=True, reverse_video=True, reverse_audio=False)
result = ReverseEngine.build_audio_filter(config)
assert result == ""
def test_enabled_normal_duration(self):
config = ReverseConfig(enabled=True)
result = ReverseEngine.build_audio_filter(config, duration=10.0)
assert result == "areverse"
def test_zero_duration(self):
config = ReverseConfig(enabled=True)
result = ReverseEngine.build_audio_filter(config, duration=0.0)
assert result == "areverse"
def test_exactly_max_safe_duration(self):
config = ReverseConfig(enabled=True)
result = ReverseEngine.build_audio_filter(
config, duration=ReverseEngine.MAX_SAFE_DURATION
)
assert result == "areverse"
def test_exceeds_max_safe_duration_skips(self):
config = ReverseConfig(enabled=True)
result = ReverseEngine.build_audio_filter(
config, duration=ReverseEngine.MAX_SAFE_DURATION + 1
)
assert result == ""
def test_both_video_and_audio_disabled(self):
"""两个都关,两个滤镜都为空."""
config = ReverseConfig(
enabled=True, reverse_video=False, reverse_audio=False
)
assert ReverseEngine.build_video_filter(config, 10) == ""
assert ReverseEngine.build_audio_filter(config, 10) == ""