test(wave190): preset_voices 预置音色 +35测 #1152

Merged
xiaoxia merged 2 commits from test/wave190-preset-voices into develop 2026-07-30 00:24:16 +08:00
+245
View File
@@ -0,0 +1,245 @@
"""preset_voices 预置音色配置单测."""
from dataclasses import FrozenInstanceError
import pytest
from domain.preset_voices import (
PRESET_VOICES,
PresetVoice,
get_preset_voice_by_id,
get_preset_voices,
is_preset_voice,
)
# ── PresetVoice dataclass ────────────────────────────────────────────────────
class TestPresetVoice:
"""PresetVoice dataclass"""
def test_minimal_creation(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"
assert v.language == "zh-CN"
assert v.preview_url == ""
assert v.tags is None
def test_full_creation(self):
v = PresetVoice(
voice_id="test_v2",
name="完整音色",
description="完整描述",
gender="male",
language="en-US",
preview_url="https://example.com/preview.mp3",
tags=["沉稳", "男声"],
)
assert v.gender == "male"
assert v.language == "en-US"
assert v.preview_url == "https://example.com/preview.mp3"
assert v.tags == ["沉稳", "男声"]
def test_frozen_immutable(self):
v = PresetVoice(voice_id="test", name="Test", description="desc", gender="female")
with pytest.raises(FrozenInstanceError):
v.name = "NewName"
def test_equality(self):
v1 = PresetVoice(voice_id="same", name="同名", description="d", gender="female")
v2 = PresetVoice(voice_id="same", name="同名", description="d", gender="female")
assert v1 == v2
def test_inequality(self):
v1 = PresetVoice(voice_id="a", name="A", description="da", gender="female")
v2 = PresetVoice(voice_id="b", name="B", description="db", gender="male")
assert v1 != v2
def test_to_dict(self):
v = PresetVoice(
voice_id="test_v1",
name="测试音色",
description="测试描述",
gender="female",
language="zh-CN",
preview_url="https://x.com/a.mp3",
tags=["温柔", "女声"],
)
d = v.to_dict()
assert isinstance(d, dict)
assert d["voice_id"] == "test_v1"
assert d["name"] == "测试音色"
assert d["description"] == "测试描述"
assert d["gender"] == "female"
assert d["language"] == "zh-CN"
assert d["preview_url"] == "https://x.com/a.mp3"
assert d["tags"] == ["温柔", "女声"]
def test_to_dict_none_tags_becomes_empty_list(self):
v = PresetVoice(voice_id="test", name="Test", description="desc", gender="female")
d = v.to_dict()
assert d["tags"] == []
assert isinstance(d["tags"], list)
def test_to_dict_has_all_keys(self):
v = PresetVoice(voice_id="test", name="Test", description="desc", gender="female")
d = v.to_dict()
assert set(d.keys()) == {
"voice_id",
"name",
"description",
"gender",
"language",
"preview_url",
"tags",
}
def test_slots_no_extra_attrs(self):
v = PresetVoice(voice_id="test", name="Test", description="desc", gender="female")
# frozen + slots dataclass 不允许动态添加属性
with pytest.raises((AttributeError, TypeError)):
v.nonexistent_field = "value"
# ── PRESET_VOICES 列表 ───────────────────────────────────────────────────────
class TestPresetVoicesList:
"""PRESET_VOICES 预置音色列表"""
def test_not_empty(self):
assert len(PRESET_VOICES) > 0
def test_count(self):
assert len(PRESET_VOICES) == 8
def test_all_are_preset_voice(self):
for v in PRESET_VOICES:
assert isinstance(v, PresetVoice)
def test_unique_voice_ids(self):
ids = [v.voice_id for v in PRESET_VOICES]
assert len(ids) == len(set(ids))
def test_unique_names(self):
names = [v.name for v in PRESET_VOICES]
assert len(names) == len(set(names))
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")
def test_all_chinese(self):
for v in PRESET_VOICES:
assert v.language == "zh-CN"
def test_longxiaochun_voice(self):
v = next(v for v in PRESET_VOICES if v.voice_id == "longxiaochun_v3")
assert v.name == "龙小淳"
assert v.gender == "female"
assert "温柔" in v.description
def test_longxiaochen_voice(self):
v = next(v for v in PRESET_VOICES if v.voice_id == "longxiaochen_v3")
assert v.name == "龙小晨"
assert v.gender == "male"
def test_male_voices_count(self):
males = [v for v in PRESET_VOICES if v.gender == "male"]
assert len(males) == 3 # 龙小晨/龙书/龙博
def test_female_voices_count(self):
females = [v for v in PRESET_VOICES if v.gender == "female"]
assert len(females) == 5 # 龙小淳/龙小夏/龙悦/龙静/龙甜
def test_all_have_tags(self):
for v in PRESET_VOICES:
assert v.tags is not None
assert len(v.tags) > 0
def test_voice_id_pattern(self):
# 所有音色 ID 都以 _v3 结尾
for v in PRESET_VOICES:
assert v.voice_id.endswith("_v3")
# ── 工具函数 ─────────────────────────────────────────────────────────────────
class TestGetPresetVoices:
"""get_preset_voices 函数"""
def test_returns_full_list(self):
result = get_preset_voices()
assert len(result) == len(PRESET_VOICES)
assert result is PRESET_VOICES # 返回同一列表引用
def test_all_are_preset_voice(self):
result = get_preset_voices()
for v in result:
assert isinstance(v, PresetVoice)
class TestGetPresetVoiceById:
"""get_preset_voice_by_id 函数"""
def test_get_existing_female(self):
v = get_preset_voice_by_id("longxiaochun_v3")
assert v is not None
assert v.voice_id == "longxiaochun_v3"
assert v.name == "龙小淳"
def test_get_existing_male(self):
v = get_preset_voice_by_id("longxiaochen_v3")
assert v is not None
assert v.gender == "male"
def test_get_nonexistent_returns_none(self):
v = get_preset_voice_by_id("nonexistent_voice")
assert v is None
def test_get_empty_string_returns_none(self):
v = get_preset_voice_by_id("")
assert v is None
def test_returns_same_instance(self):
v1 = get_preset_voice_by_id("longyue_v3")
v2 = get_preset_voice_by_id("longyue_v3")
assert v1 is v2
def test_all_voices_reachable(self):
for v in PRESET_VOICES:
found = get_preset_voice_by_id(v.voice_id)
assert found is not None
assert found.voice_id == v.voice_id
class TestIsPresetVoice:
"""is_preset_voice 函数"""
def test_existing_voice_true(self):
assert is_preset_voice("longxiaochun_v3") is True
def test_all_existing_are_true(self):
for v in PRESET_VOICES:
assert is_preset_voice(v.voice_id) is True
def test_nonexistent_voice_false(self):
assert is_preset_voice("fake_voice") is False
def test_empty_string_false(self):
assert is_preset_voice("") is False
def test_consistent_with_get_by_id(self):
for v in PRESET_VOICES:
assert is_preset_voice(v.voice_id) == (get_preset_voice_by_id(v.voice_id) is not None)