From 72651cabc443f8431b533a48e56f12fa1cca8b68 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Wed, 29 Jul 2026 18:49:33 +0800 Subject: [PATCH 1/2] =?UTF-8?q?test(wave189):=20preset=5Fbgm=20=E9=A2=84?= =?UTF-8?q?=E8=AE=BEBGM=E5=BA=93=20+44=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/unit/domain/test_preset_bgm.py | 300 +++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100755 tests/unit/domain/test_preset_bgm.py diff --git a/tests/unit/domain/test_preset_bgm.py b/tests/unit/domain/test_preset_bgm.py new file mode 100755 index 000000000..41efc3a8e --- /dev/null +++ b/tests/unit/domain/test_preset_bgm.py @@ -0,0 +1,300 @@ +"""preset_bgm 预设BGM库单测.""" + +from dataclasses import FrozenInstanceError + +import pytest + +from domain.preset_bgm import ( + BGM_STYLES, + PRESET_BGM_LIBRARY, + PresetBGM, + get_preset_bgm, + list_preset_bgm_by_style, + search_preset_bgm, +) + +# ── PresetBGM dataclass ────────────────────────────────────────────────────── + + +class TestPresetBGM: + """PresetBGM dataclass""" + + def test_minimal_creation(self): + b = PresetBGM(id="test_001", name="测试音乐", style="upbeat", duration=60.0) + assert b.id == "test_001" + assert b.name == "测试音乐" + assert b.style == "upbeat" + assert b.duration == 60.0 + assert b.artist == "" + assert b.description == "" + assert b.tags == [] + assert b.audio_url == "" + + def test_full_creation(self): + b = PresetBGM( + id="bgm_001", + name="阳光清晨", + style="upbeat", + duration=120.5, + artist="音乐人A", + description="轻快明亮的吉他", + tags=["轻快", "阳光"], + audio_url="https://cdn.example.com/bgm.mp3", + ) + assert b.id == "bgm_001" + assert b.artist == "音乐人A" + assert b.description == "轻快明亮的吉他" + assert b.tags == ["轻快", "阳光"] + assert b.audio_url == "https://cdn.example.com/bgm.mp3" + + def test_frozen_immutable(self): + b = PresetBGM(id="test", name="Test", style="relax", duration=100.0) + with pytest.raises(FrozenInstanceError): + b.name = "NewName" + + def test_equality(self): + b1 = PresetBGM(id="same", name="同名", style="upbeat", duration=60.0) + b2 = PresetBGM(id="same", name="同名", style="upbeat", duration=60.0) + assert b1 == b2 + + def test_inequality(self): + b1 = PresetBGM(id="a", name="A", style="upbeat", duration=60.0) + b2 = PresetBGM(id="b", name="B", style="relax", duration=90.0) + assert b1 != b2 + + def test_not_hashable_due_to_list_tags(self): + # 包含 list 字段(tags)的 frozen dataclass 不可哈希 + b = PresetBGM(id="test", name="Test", style="tech", duration=60.0) + with pytest.raises(TypeError): + hash(b) + + +# ── PRESET_BGM_LIBRARY 清单 ────────────────────────────────────────────────── + + +class TestPresetBGMLibrary: + """预设BGM库清单""" + + def test_not_empty(self): + assert len(PRESET_BGM_LIBRARY) > 0 + + def test_all_are_preset_bgm(self): + for bgm in PRESET_BGM_LIBRARY: + assert isinstance(bgm, PresetBGM) + + def test_unique_ids(self): + ids = [b.id for b in PRESET_BGM_LIBRARY] + assert len(ids) == len(set(ids)) + + def test_all_have_required_fields(self): + for bgm in PRESET_BGM_LIBRARY: + assert bgm.id != "" + assert bgm.name != "" + assert bgm.style != "" + assert bgm.duration > 0 + + def test_upbeat_style_count(self): + upbeats = [b for b in PRESET_BGM_LIBRARY if b.style == "upbeat"] + assert len(upbeats) >= 3 + + def test_relax_style_count(self): + relax = [b for b in PRESET_BGM_LIBRARY if b.style == "relax"] + assert len(relax) >= 3 + + def test_tech_style_count(self): + tech = [b for b in PRESET_BGM_LIBRARY if b.style == "tech"] + assert len(tech) >= 2 + + def test_commerce_style_count(self): + commerce = [b for b in PRESET_BGM_LIBRARY if b.style == "commerce"] + assert len(commerce) >= 2 + + def test_sunny_morning_preset(self): + b = next(b for b in PRESET_BGM_LIBRARY if b.id == "bgm_upbeat_001") + assert b.name == "阳光清晨" + assert b.style == "upbeat" + assert b.duration == 120.0 + assert "吉他" in b.description + assert "vlog" in b.tags + + def test_quiet_time_preset(self): + b = next(b for b in PRESET_BGM_LIBRARY if b.id == "bgm_relax_001") + assert b.name == "静谧时光" + assert b.style == "relax" + assert b.duration == 180.0 + + def test_future_tech_preset(self): + b = next(b for b in PRESET_BGM_LIBRARY if b.id == "bgm_tech_001") + assert b.name == "未来科技" + assert b.style == "tech" + + def test_all_durations_positive(self): + for bgm in PRESET_BGM_LIBRARY: + assert bgm.duration > 0 + + def test_all_tags_are_lists(self): + for bgm in PRESET_BGM_LIBRARY: + assert isinstance(bgm.tags, list) + + +# ── BGM_STYLES 风格字典 ───────────────────────────────────────────────────── + + +class TestBGMStyles: + """BGM_STYLES 风格分类字典""" + + def test_styles_exist(self): + assert "upbeat" in BGM_STYLES + assert "relax" in BGM_STYLES + assert "tech" in BGM_STYLES + assert "commerce" in BGM_STYLES + assert "emotional" in BGM_STYLES + assert "cinematic" in BGM_STYLES + + def test_style_names_chinese(self): + assert BGM_STYLES["upbeat"] == "轻快" + assert BGM_STYLES["relax"] == "治愈" + assert BGM_STYLES["tech"] == "科技" + assert BGM_STYLES["commerce"] == "电商" + assert BGM_STYLES["emotional"] == "情感" + assert BGM_STYLES["cinematic"] == "电影" + + def test_library_styles_are_defined(self): + # 库中的所有风格都应该在 BGM_STYLES 中有定义 + styles_in_library = {b.style for b in PRESET_BGM_LIBRARY} + for style in styles_in_library: + assert style in BGM_STYLES, f"style {style} not defined in BGM_STYLES" + + +# ── get_preset_bgm ────────────────────────────────────────────────────────── + + +class TestGetPresetBGM: + """get_preset_bgm 函数""" + + def test_get_existing(self): + b = get_preset_bgm("bgm_upbeat_001") + assert b is not None + assert b.id == "bgm_upbeat_001" + assert b.name == "阳光清晨" + + def test_get_relax(self): + b = get_preset_bgm("bgm_relax_002") + assert b is not None + assert b.style == "relax" + + def test_get_nonexistent_returns_none(self): + b = get_preset_bgm("nonexistent_id") + assert b is None + + def test_get_empty_string_returns_none(self): + b = get_preset_bgm("") + assert b is None + + def test_returns_same_instance(self): + b1 = get_preset_bgm("bgm_upbeat_001") + b2 = get_preset_bgm("bgm_upbeat_001") + assert b1 is b2 + + +# ── list_preset_bgm_by_style ───────────────────────────────────────────────── + + +class TestListPresetBGMByStyle: + """list_preset_bgm_by_style 函数""" + + def test_upbeat_style(self): + result = list_preset_bgm_by_style("upbeat") + assert len(result) >= 3 + for b in result: + assert b.style == "upbeat" + + def test_relax_style(self): + result = list_preset_bgm_by_style("relax") + assert len(result) >= 3 + for b in result: + assert b.style == "relax" + + def test_tech_style(self): + result = list_preset_bgm_by_style("tech") + assert len(result) >= 2 + + def test_commerce_style(self): + result = list_preset_bgm_by_style("commerce") + assert len(result) >= 2 + + def test_unknown_style_empty(self): + result = list_preset_bgm_by_style("nonexistent_style") + assert len(result) == 0 + + def test_empty_string_empty(self): + result = list_preset_bgm_by_style("") + assert len(result) == 0 + + def test_returns_new_list(self): + # 修改返回值不应影响原始列表 + result = list_preset_bgm_by_style("upbeat") + result.clear() + assert len(list_preset_bgm_by_style("upbeat")) >= 3 + + +# ── search_preset_bgm ──────────────────────────────────────────────────────── + + +class TestSearchPresetBGM: + """search_preset_bgm 函数""" + + def test_search_by_name(self): + result = search_preset_bgm("阳光") + assert len(result) >= 1 + assert any("阳光" in b.name for b in result) + + def test_search_by_description(self): + result = search_preset_bgm("钢琴") + assert len(result) >= 1 + # 应该匹配描述里有钢琴的 + + def test_search_by_tag(self): + result = search_preset_bgm("vlog") + assert len(result) >= 1 + assert any("vlog" in b.tags for b in result) + + def test_search_tech_keyword(self): + result = search_preset_bgm("科技") + assert len(result) >= 2 + + def test_search_case_insensitive(self): + r1 = search_preset_bgm("UPBEAT") + r2 = search_preset_bgm("upbeat") + assert len(r1) == len(r2) + + def test_search_no_match(self): + result = search_preset_bgm("完全不存在的关键词_xyz123") + assert len(result) == 0 + + def test_search_empty_string(self): + # 空字符串应该匹配所有(因为 "" in any string 是 True) + result = search_preset_bgm("") + assert len(result) == len(PRESET_BGM_LIBRARY) + + def test_search_electronic(self): + result = search_preset_bgm("电子") + assert len(result) >= 2 + + def test_order_preserved(self): + # 搜索结果应该保持原列表顺序 + result = search_preset_bgm("bgm") + ids = [b.id for b in result] + all_ids = [b.id for b in PRESET_BGM_LIBRARY] + # 验证相对顺序 + pos_in_result = {bgm_id: i for i, bgm_id in enumerate(ids)} + prev_pos = -1 + for bgm_id in all_ids: + if bgm_id in pos_in_result: + assert pos_in_result[bgm_id] > prev_pos + prev_pos = pos_in_result[bgm_id] + + def test_search_partial_tag_match(self): + # 关键词是标签的子串也能匹配 + result = search_preset_bgm("吉他") + assert len(result) >= 1 -- 2.54.0 From e06112dfb6796f3241f20bb71bbb8eccee065dc5 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Wed, 29 Jul 2026 11:01:02 +0000 Subject: [PATCH 2/2] style: auto-format with black + isort + prettier [skip ci-format-check] --- tests/unit/domain/test_preset_bgm.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/domain/test_preset_bgm.py b/tests/unit/domain/test_preset_bgm.py index 41efc3a8e..c1b5b3e00 100755 --- a/tests/unit/domain/test_preset_bgm.py +++ b/tests/unit/domain/test_preset_bgm.py @@ -3,7 +3,6 @@ from dataclasses import FrozenInstanceError import pytest - from domain.preset_bgm import ( BGM_STYLES, PRESET_BGM_LIBRARY, -- 2.54.0