From 72e8d59f5dd030b439e2bfe19e15120b8e15a5ad Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 28 Jul 2026 13:41:19 +0800 Subject: [PATCH] =?UTF-8?q?test(wave155):=20generated=5Fvideo=E7=94=9F?= =?UTF-8?q?=E6=88=90=E8=A7=86=E9=A2=91=E5=AE=9E=E4=BD=93=E5=8D=95=E6=B5=8B?= =?UTF-8?q?=20+16?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为 domain/generated_video.py 新增 16 个单测: - create 必填字段 + 默认值 - strip 行为 - 4个空值校验(project_id/task_id/name/file_url) - 唯一ID + 时间戳 - 零值合法(宽高/fps) - generation_params 独立性 --- tests/unit/domain/test_generated_video.py | 170 ++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 tests/unit/domain/test_generated_video.py diff --git a/tests/unit/domain/test_generated_video.py b/tests/unit/domain/test_generated_video.py new file mode 100644 index 000000000..c5259e5af --- /dev/null +++ b/tests/unit/domain/test_generated_video.py @@ -0,0 +1,170 @@ +"""generated_video 单测. + +domain 层生成视频实体纯逻辑模块,0 外部依赖。 +覆盖:create工厂/校验、默认值、数据完整性。 +""" + +from __future__ import annotations + +from packages.domain.generated_video import GeneratedVideo + + +class TestGeneratedVideoCreate: + """GeneratedVideo.create 工厂测试.""" + + def test_create_required_fields(self): + """最简创建(仅必填字段).""" + v = GeneratedVideo.create( + project_id="proj1", + generation_task_id="task1", + name="我的视频", + file_url="https://cdn.example.com/v.mp4", + ) + assert v.project_id == "proj1" + assert v.generation_task_id == "task1" + assert v.name == "我的视频" + assert v.file_url == "https://cdn.example.com/v.mp4" + assert isinstance(v.id, str) + assert len(v.id) > 0 + + def test_create_defaults(self): + """默认值正确.""" + v = GeneratedVideo.create( + project_id="p1", + generation_task_id="t1", + name="v", + file_url="http://x/v.mp4", + ) + assert v.file_size == 0 + assert v.duration == 0.0 + assert v.width == 0 + assert v.height == 0 + assert v.fps == 0.0 + assert v.thumbnail_url is None + assert v.status == "completed" + assert v.review_status == "pending_review" + assert v.generation_params == {} + assert v.video_fingerprint is None + assert v.is_duplicate is False + assert v.duplicate_of is None + + def test_create_with_all_fields(self): + """带全部字段创建.""" + v = GeneratedVideo.create( + project_id="proj1", + generation_task_id="task1", + name=" 测试视频 ", + file_url=" https://cdn.example.com/v.mp4 ", + file_size=1024000, + duration=120.5, + width=1920, + height=1080, + fps=30.0, + thumbnail_url="https://cdn.example.com/thumb.jpg", + generation_params={"template": "tpl1", "bgm": "bgm1"}, + ) + assert v.name == "测试视频" # strip + assert v.file_url == "https://cdn.example.com/v.mp4" # strip + assert v.file_size == 1024000 + assert v.duration == 120.5 + assert v.width == 1920 + assert v.height == 1080 + assert v.fps == 30.0 + assert v.thumbnail_url == "https://cdn.example.com/thumb.jpg" + assert v.generation_params == {"template": "tpl1", "bgm": "bgm1"} + + def test_create_strips_fields(self): + """字符串字段会 strip.""" + v = GeneratedVideo.create( + project_id=" p1 ", + generation_task_id=" t1 ", + name=" v ", + file_url=" http://x/v ", + ) + assert v.project_id == "p1" + assert v.generation_task_id == "t1" + assert v.name == "v" + assert v.file_url == "http://x/v" + + def test_create_empty_project_id(self): + """空 project_id 无效.""" + try: + GeneratedVideo.create("", "t1", "v", "http://x/v") + assert False + except ValueError as e: + assert "project_id" in str(e) + + def test_create_whitespace_project_id(self): + """纯空白 project_id 无效.""" + try: + GeneratedVideo.create(" ", "t1", "v", "http://x/v") + assert False + except ValueError as e: + assert "project_id" in str(e) + + def test_create_empty_task_id(self): + """空 generation_task_id 无效.""" + try: + GeneratedVideo.create("p1", "", "v", "http://x/v") + assert False + except ValueError as e: + assert "generation_task_id" in str(e) + + def test_create_empty_name(self): + """空 name 无效.""" + try: + GeneratedVideo.create("p1", "t1", "", "http://x/v") + assert False + except ValueError as e: + assert "name" in str(e) + + def test_create_empty_file_url(self): + """空 file_url 无效.""" + try: + GeneratedVideo.create("p1", "t1", "v", "") + assert False + except ValueError as e: + assert "file_url" in str(e) + + def test_create_whitespace_file_url(self): + """纯空白 file_url 无效.""" + try: + GeneratedVideo.create("p1", "t1", "v", " ") + assert False + except ValueError as e: + assert "file_url" in str(e) + + def test_create_generation_params_none_defaults_empty(self): + """generation_params=None 默认为空 dict.""" + v = GeneratedVideo.create("p1", "t1", "v", "http://x/v", generation_params=None) + assert v.generation_params == {} + + def test_create_unique_id(self): + """不同视频 id 不同.""" + v1 = GeneratedVideo.create("p", "t", "v", "http://x/v") + v2 = GeneratedVideo.create("p", "t", "v", "http://x/v") + assert v1.id != v2.id + + def test_create_has_timestamps(self): + """有生成和创建时间.""" + v = GeneratedVideo.create("p", "t", "v", "http://x/v") + assert v.generated_at is not None + assert v.created_at is not None + + def test_zero_dimensions_valid(self): + """宽高为 0 合法(未指定分辨率).""" + v = GeneratedVideo.create("p", "t", "v", "http://x/v", width=0, height=0) + assert v.width == 0 + assert v.height == 0 + + def test_zero_fps_valid(self): + """fps 为 0 合法.""" + v = GeneratedVideo.create("p", "t", "v", "http://x/v", fps=0.0) + assert v.fps == 0.0 + + def test_generation_params_independent(self): + """不同实例的 generation_params 独立.""" + v1 = GeneratedVideo.create("p", "t", "v", "http://x/v") + v2 = GeneratedVideo.create("p", "t", "v", "http://x/v") + v1.generation_params["key"] = "value" + assert "key" not in v2.generation_params