test(unit): P3-1 第五波 新增3个领域模块单元测试(54个用例) #683
@@ -0,0 +1,166 @@
|
||||
"""
|
||||
PresetVoice 预置音色领域模型单元测试
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from domain.preset_voices import (
|
||||
PRESET_VOICES,
|
||||
PresetVoice,
|
||||
get_preset_voice_by_id,
|
||||
get_preset_voices,
|
||||
is_preset_voice,
|
||||
)
|
||||
|
||||
|
||||
class TestPresetVoice:
|
||||
"""PresetVoice 数据类测试"""
|
||||
|
||||
def test_create_required_fields(self):
|
||||
v = PresetVoice(
|
||||
voice_id="test_v1",
|
||||
name="测试音色",
|
||||
description="测试描述",
|
||||
gender="female",
|
||||
)
|
||||
assert v.voice_id == "test_v1"
|
||||
assert v.name == "测试音色"
|
||||
assert v.description == "测试描述"
|
||||
assert v.gender == "female"
|
||||
|
||||
def test_default_language(self):
|
||||
v = PresetVoice(voice_id="v1", name="n", description="d", gender="female")
|
||||
assert v.language == "zh-CN"
|
||||
|
||||
def test_default_preview_url(self):
|
||||
v = PresetVoice(voice_id="v1", name="n", description="d", gender="female")
|
||||
assert v.preview_url == ""
|
||||
|
||||
def test_default_tags_none(self):
|
||||
v = PresetVoice(voice_id="v1", name="n", description="d", gender="female")
|
||||
assert v.tags is None
|
||||
|
||||
def test_custom_tags(self):
|
||||
v = PresetVoice(
|
||||
voice_id="v1",
|
||||
name="n",
|
||||
description="d",
|
||||
gender="female",
|
||||
tags=["温柔", "女声"],
|
||||
)
|
||||
assert v.tags == ["温柔", "女声"]
|
||||
|
||||
def test_is_frozen(self):
|
||||
v = PresetVoice(voice_id="v1", name="n", description="d", gender="female")
|
||||
with pytest.raises(AttributeError):
|
||||
v.name = "改了"
|
||||
|
||||
|
||||
class TestPresetVoiceToDict:
|
||||
"""to_dict 序列化测试"""
|
||||
|
||||
def test_to_dict_basic(self):
|
||||
v = PresetVoice(
|
||||
voice_id="longxiaochun_v3",
|
||||
name="龙小淳",
|
||||
description="温柔女声",
|
||||
gender="female",
|
||||
language="zh-CN",
|
||||
preview_url="https://example.com/audio.mp3",
|
||||
tags=["温柔", "女声"],
|
||||
)
|
||||
d = v.to_dict()
|
||||
assert d["voice_id"] == "longxiaochun_v3"
|
||||
assert d["name"] == "龙小淳"
|
||||
assert d["description"] == "温柔女声"
|
||||
assert d["gender"] == "female"
|
||||
assert d["language"] == "zh-CN"
|
||||
assert d["preview_url"] == "https://example.com/audio.mp3"
|
||||
assert d["tags"] == ["温柔", "女声"]
|
||||
|
||||
def test_to_dict_tags_none_becomes_empty_list(self):
|
||||
v = PresetVoice(voice_id="v1", name="n", description="d", gender="female")
|
||||
d = v.to_dict()
|
||||
assert d["tags"] == []
|
||||
|
||||
|
||||
class TestPresetVoiceList:
|
||||
"""预置音色列表测试"""
|
||||
|
||||
def test_list_not_empty(self):
|
||||
voices = get_preset_voices()
|
||||
assert len(voices) > 0
|
||||
|
||||
def test_all_are_preset_voice_instances(self):
|
||||
for v in PRESET_VOICES:
|
||||
assert isinstance(v, PresetVoice)
|
||||
|
||||
def test_voice_ids_unique(self):
|
||||
ids = [v.voice_id for v in PRESET_VOICES]
|
||||
assert len(ids) == len(set(ids))
|
||||
|
||||
def test_all_have_required_fields(self):
|
||||
for v in PRESET_VOICES:
|
||||
assert v.voice_id
|
||||
assert v.name
|
||||
assert v.description
|
||||
assert v.gender in ("male", "female")
|
||||
assert v.language
|
||||
|
||||
def test_total_count(self):
|
||||
assert len(PRESET_VOICES) == 8
|
||||
|
||||
|
||||
class TestGetPresetVoiceById:
|
||||
"""按 ID 查询预置音色测试"""
|
||||
|
||||
def test_existing_voice(self):
|
||||
v = get_preset_voice_by_id("longxiaochun_v3")
|
||||
assert v is not None
|
||||
assert v.name == "龙小淳"
|
||||
assert v.gender == "female"
|
||||
|
||||
def test_nonexistent_voice(self):
|
||||
v = get_preset_voice_by_id("nonexistent_voice")
|
||||
assert v is None
|
||||
|
||||
def test_empty_string(self):
|
||||
v = get_preset_voice_by_id("")
|
||||
assert v is None
|
||||
|
||||
|
||||
class TestIsPresetVoice:
|
||||
"""判断是否预置音色测试"""
|
||||
|
||||
def test_existing_is_preset(self):
|
||||
assert is_preset_voice("longxiaochen_v3") is True
|
||||
|
||||
def test_nonexistent_not_preset(self):
|
||||
assert is_preset_voice("custom_voice_123") is False
|
||||
|
||||
def test_empty_not_preset(self):
|
||||
assert is_preset_voice("") is False
|
||||
|
||||
|
||||
class TestPresetVoiceSamples:
|
||||
"""预置音色样本验证"""
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"voice_id,expected_name,gender",
|
||||
[
|
||||
("longxiaochun_v3", "龙小淳", "female"),
|
||||
("longxiaoxia_v3", "龙小夏", "female"),
|
||||
("longxiaochen_v3", "龙小晨", "male"),
|
||||
("longyue_v3", "龙悦", "female"),
|
||||
("longshu_v3", "龙书", "male"),
|
||||
("longjing_v3", "龙静", "female"),
|
||||
("longbo_v3", "龙博", "male"),
|
||||
("longtian_v3", "龙甜", "female"),
|
||||
],
|
||||
)
|
||||
def test_all_preset_voices_sample(self, voice_id, expected_name, gender):
|
||||
v = get_preset_voice_by_id(voice_id)
|
||||
assert v is not None
|
||||
assert v.name == expected_name
|
||||
assert v.gender == gender
|
||||
assert v.language == "zh-CN"
|
||||
assert len(v.tags or []) >= 2
|
||||
@@ -0,0 +1,153 @@
|
||||
"""
|
||||
Template 模板领域模型单元测试
|
||||
"""
|
||||
|
||||
from domain.template import Template, TemplateCategory, TemplateSegment
|
||||
|
||||
|
||||
class TestTemplateSegment:
|
||||
"""TemplateSegment 测试"""
|
||||
|
||||
def test_create_segment(self):
|
||||
seg = TemplateSegment(
|
||||
id="seg-1",
|
||||
template_id="tpl-1",
|
||||
segment_order=1,
|
||||
duration_min=3.0,
|
||||
duration_max=5.0,
|
||||
)
|
||||
assert seg.id == "seg-1"
|
||||
assert seg.template_id == "tpl-1"
|
||||
assert seg.segment_order == 1
|
||||
assert seg.duration_min == 3.0
|
||||
assert seg.duration_max == 5.0
|
||||
assert seg.material_type is None
|
||||
|
||||
def test_segment_with_material_type(self):
|
||||
seg = TemplateSegment(
|
||||
id="seg-1",
|
||||
template_id="tpl-1",
|
||||
segment_order=0,
|
||||
duration_min=2.0,
|
||||
duration_max=4.0,
|
||||
material_type="人物",
|
||||
)
|
||||
assert seg.material_type == "人物"
|
||||
|
||||
def test_segment_has_timestamps(self):
|
||||
seg = TemplateSegment(
|
||||
id="seg-1",
|
||||
template_id="tpl-1",
|
||||
segment_order=1,
|
||||
duration_min=1.0,
|
||||
duration_max=2.0,
|
||||
)
|
||||
assert seg.created_at is not None
|
||||
assert seg.updated_at is not None
|
||||
|
||||
|
||||
class TestTemplate:
|
||||
"""Template 测试"""
|
||||
|
||||
def test_create_template_minimal(self):
|
||||
t = Template(
|
||||
id="tpl-1",
|
||||
user_id="user-1",
|
||||
name="测试模板",
|
||||
mode="one_take",
|
||||
)
|
||||
assert t.id == "tpl-1"
|
||||
assert t.user_id == "user-1"
|
||||
assert t.name == "测试模板"
|
||||
assert t.mode == "one_take"
|
||||
|
||||
def test_default_values(self):
|
||||
t = Template(id="tpl-1", user_id="u1", name="n", mode="one_take")
|
||||
assert t.category == ""
|
||||
assert t.tags == []
|
||||
assert t.title_config == {}
|
||||
assert t.subtitle_config == {}
|
||||
assert t.bgm_config == {}
|
||||
assert t.estimated_duration == 0.0
|
||||
assert t.segments == []
|
||||
assert t.is_active is True
|
||||
|
||||
def test_with_segments(self):
|
||||
segs = [
|
||||
TemplateSegment(id="s1", template_id="t1", segment_order=0, duration_min=2, duration_max=4),
|
||||
TemplateSegment(id="s2", template_id="t1", segment_order=1, duration_min=3, duration_max=5),
|
||||
]
|
||||
t = Template(
|
||||
id="tpl-1",
|
||||
user_id="u1",
|
||||
name="n",
|
||||
mode="voice_over",
|
||||
segments=segs,
|
||||
)
|
||||
assert len(t.segments) == 2
|
||||
assert t.segments[0].segment_order == 0
|
||||
assert t.segments[1].segment_order == 1
|
||||
|
||||
def test_all_modes(self):
|
||||
for mode in ["pip", "voice_pip", "one_take", "voice_over"]:
|
||||
t = Template(id="t1", user_id="u1", name="n", mode=mode)
|
||||
assert t.mode == mode
|
||||
|
||||
def test_with_configs(self):
|
||||
t = Template(
|
||||
id="t1",
|
||||
user_id="u1",
|
||||
name="n",
|
||||
mode="one_take",
|
||||
title_config={"font_size": 24, "color": "#ffffff"},
|
||||
subtitle_config={"style": "bottom"},
|
||||
bgm_config={"volume": 0.5},
|
||||
)
|
||||
assert t.title_config["font_size"] == 24
|
||||
assert t.subtitle_config["style"] == "bottom"
|
||||
assert t.bgm_config["volume"] == 0.5
|
||||
|
||||
def test_estimated_duration(self):
|
||||
t = Template(
|
||||
id="t1",
|
||||
user_id="u1",
|
||||
name="n",
|
||||
mode="one_take",
|
||||
estimated_duration=30.5,
|
||||
)
|
||||
assert t.estimated_duration == 30.5
|
||||
|
||||
def test_is_active_false(self):
|
||||
t = Template(id="t1", user_id="u1", name="n", mode="one_take", is_active=False)
|
||||
assert t.is_active is False
|
||||
|
||||
def test_has_timestamps(self):
|
||||
t = Template(id="t1", user_id="u1", name="n", mode="one_take")
|
||||
assert t.created_at is not None
|
||||
assert t.updated_at is not None
|
||||
|
||||
def test_tags_list(self):
|
||||
t = Template(
|
||||
id="t1",
|
||||
user_id="u1",
|
||||
name="n",
|
||||
mode="one_take",
|
||||
tags=["风景", "vlog"],
|
||||
)
|
||||
assert "风景" in t.tags
|
||||
assert "vlog" in t.tags
|
||||
assert len(t.tags) == 2
|
||||
|
||||
|
||||
class TestTemplateCategory:
|
||||
"""TemplateCategory 测试"""
|
||||
|
||||
def test_create_category(self):
|
||||
cat = TemplateCategory(id="cat-1", user_id="u1", name="风景")
|
||||
assert cat.id == "cat-1"
|
||||
assert cat.user_id == "u1"
|
||||
assert cat.name == "风景"
|
||||
|
||||
def test_category_has_timestamp(self):
|
||||
cat = TemplateCategory(id="cat-1", user_id="u1", name="风景")
|
||||
assert cat.created_at is not None
|
||||
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
EditTemplateVersion 模板版本领域模型单元测试
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from domain.template_version import EditTemplateVersion
|
||||
|
||||
|
||||
class TestEditTemplateVersionCreate:
|
||||
"""创建模板版本测试"""
|
||||
|
||||
def test_create_required_fields(self):
|
||||
v = EditTemplateVersion.create(template_id="tpl-1", version=1)
|
||||
assert v.id is not None
|
||||
assert len(v.id) == 32
|
||||
assert v.template_id == "tpl-1"
|
||||
assert v.version == 1
|
||||
|
||||
def test_default_values(self):
|
||||
v = EditTemplateVersion.create(template_id="tpl-1", version=1)
|
||||
assert v.name == ""
|
||||
assert v.editing_mode == "one_take"
|
||||
assert v.config == {}
|
||||
assert v.clip_configs == []
|
||||
assert v.change_note == ""
|
||||
assert v.published_by == ""
|
||||
|
||||
def test_with_name_and_mode(self):
|
||||
v = EditTemplateVersion.create(
|
||||
template_id="tpl-1",
|
||||
version=2,
|
||||
name="风景Vlog模板",
|
||||
editing_mode="voice_over",
|
||||
)
|
||||
assert v.name == "风景Vlog模板"
|
||||
assert v.editing_mode == "voice_over"
|
||||
|
||||
def test_with_config(self):
|
||||
config = {
|
||||
"title": {"font_size": 24},
|
||||
"subtitle": {"style": "bottom"},
|
||||
"bgm": {"volume": 0.5},
|
||||
}
|
||||
v = EditTemplateVersion.create(
|
||||
template_id="tpl-1",
|
||||
version=1,
|
||||
config=config,
|
||||
)
|
||||
assert v.config == config
|
||||
assert v.config["title"]["font_size"] == 24
|
||||
|
||||
def test_with_clip_configs(self):
|
||||
clips = [
|
||||
{"clip_id": 1, "duration": 3.0, "transition": "fade"},
|
||||
{"clip_id": 2, "duration": 5.0, "transition": "slide"},
|
||||
]
|
||||
v = EditTemplateVersion.create(
|
||||
template_id="tpl-1",
|
||||
version=1,
|
||||
clip_configs=clips,
|
||||
)
|
||||
assert len(v.clip_configs) == 2
|
||||
assert v.clip_configs[0]["clip_id"] == 1
|
||||
|
||||
def test_config_none_defaults_to_empty_dict(self):
|
||||
v = EditTemplateVersion.create(template_id="tpl-1", version=1, config=None)
|
||||
assert v.config == {}
|
||||
|
||||
def test_clip_configs_none_defaults_to_empty_list(self):
|
||||
v = EditTemplateVersion.create(template_id="tpl-1", version=1, clip_configs=None)
|
||||
assert v.clip_configs == []
|
||||
|
||||
def test_with_change_note(self):
|
||||
v = EditTemplateVersion.create(
|
||||
template_id="tpl-1",
|
||||
version=3,
|
||||
change_note="优化转场效果,新增滤镜",
|
||||
)
|
||||
assert v.change_note == "优化转场效果,新增滤镜"
|
||||
|
||||
def test_with_published_by(self):
|
||||
v = EditTemplateVersion.create(
|
||||
template_id="tpl-1",
|
||||
version=1,
|
||||
published_by="user-123",
|
||||
)
|
||||
assert v.published_by == "user-123"
|
||||
|
||||
def test_full_version(self):
|
||||
config = {"bgm": {"volume": 0.3}}
|
||||
clips = [{"clip_id": 1, "duration": 2.5}]
|
||||
v = EditTemplateVersion.create(
|
||||
template_id="tpl-abc",
|
||||
version=5,
|
||||
name="正式版v5",
|
||||
editing_mode="one_take",
|
||||
config=config,
|
||||
clip_configs=clips,
|
||||
change_note="第五次发布",
|
||||
published_by="admin",
|
||||
)
|
||||
assert v.template_id == "tpl-abc"
|
||||
assert v.version == 5
|
||||
assert v.name == "正式版v5"
|
||||
assert v.editing_mode == "one_take"
|
||||
assert v.config == config
|
||||
assert v.clip_configs == clips
|
||||
assert v.change_note == "第五次发布"
|
||||
assert v.published_by == "admin"
|
||||
|
||||
def test_version_number(self):
|
||||
for ver in [1, 2, 5, 10, 99]:
|
||||
v = EditTemplateVersion.create(template_id="t1", version=ver)
|
||||
assert v.version == ver
|
||||
|
||||
def test_has_created_at(self):
|
||||
v = EditTemplateVersion.create(template_id="t1", version=1)
|
||||
assert v.created_at is not None
|
||||
|
||||
|
||||
class TestEditTemplateVersionSlots:
|
||||
"""slots 模式属性测试"""
|
||||
|
||||
def test_cannot_add_new_attribute(self):
|
||||
v = EditTemplateVersion.create(template_id="t1", version=1)
|
||||
with pytest.raises(AttributeError):
|
||||
v.nonexistent_field = "value" # type: ignore[attr-defined]
|
||||
Reference in New Issue
Block a user