Files
xiaoxia-saas/tests/unit/test_chroma_key_config.py

282 lines
10 KiB
Python
Executable File

"""chroma_key_config 领域模型单测."""
from __future__ import annotations
import pytest
from packages.domain.chroma_key_config import (
CHROMA_KEY_PRESETS,
ChromaKeyConfig,
apply_chroma_key_if_needed,
build_chromakey_filter,
build_colorkey_filter,
get_preset_names,
normalize_color,
)
# ── ChromaKeyConfig.from_dict 测试 ────────────────────────────────────────
class TestChromaKeyConfigFromDict:
def test_none_returns_disabled(self):
cfg = ChromaKeyConfig.from_dict(None)
assert cfg.enabled is False
def test_empty_dict_returns_disabled(self):
cfg = ChromaKeyConfig.from_dict({})
assert cfg.enabled is False
def test_disabled_returns_disabled(self):
cfg = ChromaKeyConfig.from_dict({"enabled": False})
assert cfg.enabled is False
def test_enabled_default_params(self):
cfg = ChromaKeyConfig.from_dict({"enabled": True})
assert cfg.enabled is True
assert cfg.key_color == "#00FF00"
assert cfg.similarity == 0.3
assert cfg.blend == 0.1
assert cfg.spill_suppress == 0.0
def test_custom_params(self):
cfg = ChromaKeyConfig.from_dict(
{
"enabled": True,
"key_color": "#0000FF",
"similarity": 0.5,
"blend": 0.2,
"spill_suppress": 0.4,
}
)
assert cfg.key_color == "#0000FF"
assert cfg.similarity == 0.5
assert cfg.blend == 0.2
assert cfg.spill_suppress == 0.4
def test_similarity_clamped_low(self):
cfg = ChromaKeyConfig.from_dict({"enabled": True, "similarity": 0.001})
assert cfg.similarity == 0.01
def test_similarity_clamped_high(self):
cfg = ChromaKeyConfig.from_dict({"enabled": True, "similarity": 2.0})
assert cfg.similarity == 1.0
def test_blend_clamped_low(self):
cfg = ChromaKeyConfig.from_dict({"enabled": True, "blend": -0.5})
assert cfg.blend == 0.0
def test_blend_clamped_high(self):
cfg = ChromaKeyConfig.from_dict({"enabled": True, "blend": 1.5})
assert cfg.blend == 1.0
def test_spill_suppress_clamped(self):
cfg = ChromaKeyConfig.from_dict({"enabled": True, "spill_suppress": 2.0})
assert cfg.spill_suppress == 1.0
def test_invalid_similarity_type_uses_default(self):
cfg = ChromaKeyConfig.from_dict({"enabled": True, "similarity": "high"})
assert cfg.similarity == 0.3
def test_key_color_stripped(self):
cfg = ChromaKeyConfig.from_dict({"enabled": True, "key_color": " #00FF00 "})
assert cfg.key_color == "#00FF00"
# ── from_preset 测试 ──────────────────────────────────────────────────────
class TestFromPreset:
def test_green_screen_preset(self):
cfg = ChromaKeyConfig.from_preset("green_screen")
assert cfg is not None
assert cfg.enabled is True
assert cfg.key_color == "#00FF00"
assert cfg.similarity == 0.3
def test_blue_screen_preset(self):
cfg = ChromaKeyConfig.from_preset("blue_screen")
assert cfg is not None
assert cfg.key_color == "#0000FF"
def test_invalid_preset_returns_none(self):
assert ChromaKeyConfig.from_preset("nonexistent") is None
def test_all_presets_valid(self):
for name in CHROMA_KEY_PRESETS:
cfg = ChromaKeyConfig.from_preset(name)
assert cfg is not None
assert cfg.enabled is True
# ── has_effect / validate 测试 ────────────────────────────────────────────
class TestHasEffectAndValidate:
def test_disabled_no_effect(self):
cfg = ChromaKeyConfig(enabled=False)
assert cfg.has_effect() is False
def test_enabled_has_effect(self):
cfg = ChromaKeyConfig(enabled=True, similarity=0.3)
assert cfg.has_effect() is True
def test_zero_similarity_no_effect(self):
cfg = ChromaKeyConfig(enabled=True, similarity=0.0)
# similarity 被钳制后为 0.01,所以应该有效果
# 等等,from_dict 才会钳制,直接构造不会
assert cfg.has_effect() is False
def test_validate_disabled_valid(self):
cfg = ChromaKeyConfig(enabled=False)
ok, msg = cfg.validate()
assert ok is True
assert msg == ""
def test_validate_enabled_valid(self):
cfg = ChromaKeyConfig(enabled=True, key_color="#00FF00")
ok, msg = cfg.validate()
assert ok is True
def test_validate_empty_color_invalid(self):
cfg = ChromaKeyConfig(enabled=True, key_color="")
ok, msg = cfg.validate()
assert ok is False
assert "key_color" in msg
def test_validate_similarity_out_of_range(self):
cfg = ChromaKeyConfig(enabled=True, similarity=2.0)
ok, msg = cfg.validate()
assert ok is False
assert "similarity" in msg
# ── normalize_color 测试 ──────────────────────────────────────────────────
class TestNormalizeColor:
def test_hex_with_hash(self):
assert normalize_color("#00FF00") == "0x00FF00"
def test_hex_lowercase(self):
assert normalize_color("#00ff00") == "0x00FF00"
def test_hex_without_hash(self):
assert normalize_color("00FF00") == "0x00FF00"
def test_hex_with_alpha(self):
assert normalize_color("#00FF00FF") == "0x00FF00"
def test_already_0x_format(self):
assert normalize_color("0x00FF00") == "0X00FF00"
def test_0x_lowercase(self):
assert normalize_color("0x00ff00") == "0X00FF00"
def test_color_name_passthrough(self):
assert normalize_color("green") == "green"
assert normalize_color("blue") == "blue"
def test_whitespace_stripped(self):
assert normalize_color(" #FF0000 ") == "0xFF0000"
# ── build_colorkey_filter 测试 ────────────────────────────────────────────
class TestBuildColorkeyFilter:
def test_disabled_returns_copy(self):
cfg = ChromaKeyConfig(enabled=False)
result = build_colorkey_filter(cfg, "[in]", "[out]")
assert "copy" in result
assert "[in]" in result
assert "[out]" in result
def test_basic_colorkey(self):
cfg = ChromaKeyConfig(enabled=True, key_color="#00FF00", similarity=0.3, blend=0.1)
result = build_colorkey_filter(cfg, "[v]", "[ck]")
assert "colorkey=" in result
assert "color=0x00FF00" in result
assert "similarity=0.3" in result
assert "blend=0.1" in result
assert "[v]" in result
assert "[ck]" in result
def test_with_spill_suppress(self):
cfg = ChromaKeyConfig(enabled=True, key_color="#00FF00", spill_suppress=0.5)
result = build_colorkey_filter(cfg, "[in]", "[out]")
assert "colorchannelmixer=" in result
assert "rr=" in result
assert "gg=" in result
assert "bb=" in result
def test_no_spill_suppress_no_colorchannelmixer(self):
cfg = ChromaKeyConfig(enabled=True, spill_suppress=0.0)
result = build_colorkey_filter(cfg, "[in]", "[out]")
assert "colorchannelmixer" not in result
# ── build_chromakey_filter 测试 ───────────────────────────────────────────
class TestBuildChromakeyFilter:
def test_disabled_returns_copy(self):
cfg = ChromaKeyConfig(enabled=False)
result = build_chromakey_filter(cfg, "[in]", "[out]")
assert "copy" in result
def test_basic_chromakey(self):
cfg = ChromaKeyConfig(enabled=True, key_color="#00FF00", similarity=0.3, blend=0.1)
result = build_chromakey_filter(cfg, "[v]", "[ck]")
assert "chromakey=" in result
assert "color=0x00FF00" in result
assert "similarity=0.3" in result
assert "blend=0.1" in result
def test_contains_input_and_output_labels(self):
cfg = ChromaKeyConfig(enabled=True)
result = build_chromakey_filter(cfg, "[in_v]", "[out_v]")
assert "[in_v]" in result
assert "[out_v]" in result
# ── apply_chroma_key_if_needed 测试 ───────────────────────────────────────
class TestApplyChromaKeyIfNeeded:
def test_none_config_returns_none(self):
assert apply_chroma_key_if_needed(None, "[in]", "[out]") is None
def test_no_chroma_key_returns_none(self):
assert apply_chroma_key_if_needed({}, "[in]", "[out]") is None
def test_disabled_chroma_key_returns_none(self):
config = {"chroma_key": {"enabled": False}}
assert apply_chroma_key_if_needed(config, "[in]", "[out]") is None
def test_enabled_chroma_key_returns_filter(self):
config = {"chroma_key": {"enabled": True, "key_color": "#00FF00"}}
result = apply_chroma_key_if_needed(config, "[in]", "[out]")
assert result is not None
assert "colorkey" in result
def test_invalid_config_handles_exception(self):
# 传入无效配置触发异常,应该返回 None 而不是抛出
config = {"chroma_key": "invalid_string"}
result = apply_chroma_key_if_needed(config, "[in]", "[out]")
assert result is None
# ── 预设工具函数测试 ───────────────────────────────────────────────────────
class TestPresetUtils:
def test_get_preset_names_returns_sorted_list(self):
names = get_preset_names()
assert isinstance(names, list)
assert len(names) == len(CHROMA_KEY_PRESETS)
assert names == sorted(names)
def test_all_preset_names_in_presets_dict(self):
for name in get_preset_names():
assert name in CHROMA_KEY_PRESETS