From 0a447b4b6890a8526005b87f98d3d8bcdd1ad656 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Tue, 21 Jul 2026 00:49:29 +0800 Subject: [PATCH] =?UTF-8?q?test(unit):=20=E6=96=B0=E5=A2=9E=20classificati?= =?UTF-8?q?on/generated=5Fvideo=20=E4=B8=A4=E4=B8=AA=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - classification: 12 个测试(枚举 + ClassificationJob 工厂方法) - generated_video: 11 个测试(工厂方法 + 参数校验) --- tests/unit/test_classification_domain.py | 105 +++++++++++++++ tests/unit/test_generated_video_domain.py | 148 ++++++++++++++++++++++ 2 files changed, 253 insertions(+) create mode 100755 tests/unit/test_classification_domain.py create mode 100755 tests/unit/test_generated_video_domain.py diff --git a/tests/unit/test_classification_domain.py b/tests/unit/test_classification_domain.py new file mode 100755 index 000000000..3a322eae9 --- /dev/null +++ b/tests/unit/test_classification_domain.py @@ -0,0 +1,105 @@ +"""classification 模块单元测试.""" + +import pytest + +from domain.classification import ( + AssetClassification, + AssetLibraryKind, + ClassificationJob, + ClassificationJobStatus, + IngestJobStatus, +) + + +class TestAssetLibraryKind: + """AssetLibraryKind 枚举测试.""" + + def test_values(self): + assert AssetLibraryKind.VIDEO == "video" + assert AssetLibraryKind.VOICE == "voice" + + +class TestIngestJobStatus: + """IngestJobStatus 枚举测试.""" + + def test_values(self): + assert IngestJobStatus.PENDING == "pending" + assert IngestJobStatus.PROCESSING == "processing" + assert IngestJobStatus.COMPLETED == "completed" + assert IngestJobStatus.FAILED == "failed" + + +class TestClassificationJobStatus: + """ClassificationJobStatus 枚举测试.""" + + def test_values(self): + assert ClassificationJobStatus.PENDING == "pending" + assert ClassificationJobStatus.PROCESSING == "processing" + assert ClassificationJobStatus.COMPLETED == "completed" + assert ClassificationJobStatus.FAILED == "failed" + + +class TestAssetClassification: + """AssetClassification 枚举测试.""" + + def test_values(self): + assert AssetClassification.SCENIC == "scenic" + assert AssetClassification.PRODUCT == "product" + assert AssetClassification.PERSON == "person" + assert AssetClassification.ANIMAL == "animal" + assert AssetClassification.FOOD == "food" + assert AssetClassification.TECH == "tech" + assert AssetClassification.SPORT == "sport" + assert AssetClassification.MUSIC == "music" + assert AssetClassification.OTHER == "other" + + +class TestClassificationJobCreate: + """ClassificationJob.create 工厂方法测试.""" + + def test_create_with_valid_params(self): + job = ClassificationJob.create(project_id="proj_001", asset_id="asset_001") + assert job.id + assert len(job.id) == 32 + assert job.project_id == "proj_001" + assert job.asset_id == "asset_001" + assert job.status == ClassificationJobStatus.PENDING + assert job.classification == "" + assert job.confidence == 0.0 + assert job.error_message == "" + assert job.created_at is not None + assert job.updated_at is not None + + def test_create_strips_strings(self): + job = ClassificationJob.create( + project_id=" proj_002 ", + asset_id=" asset_002 ", + ) + assert job.project_id == "proj_002" + assert job.asset_id == "asset_002" + + def test_create_empty_project_id_raises(self): + with pytest.raises(ValueError, match="project_id"): + ClassificationJob.create(project_id="", asset_id="a") + + def test_create_whitespace_project_id_raises(self): + with pytest.raises(ValueError, match="project_id"): + ClassificationJob.create(project_id=" ", asset_id="a") + + def test_create_empty_asset_id_raises(self): + with pytest.raises(ValueError, match="asset_id"): + ClassificationJob.create(project_id="p", asset_id="") + + def test_create_whitespace_asset_id_raises(self): + with pytest.raises(ValueError, match="asset_id"): + ClassificationJob.create(project_id="p", asset_id=" ") + + def test_create_ids_are_unique(self): + j1 = ClassificationJob.create(project_id="p", asset_id="a") + j2 = ClassificationJob.create(project_id="p", asset_id="b") + assert j1.id != j2.id + + def test_create_timestamps_are_utc(self): + job = ClassificationJob.create(project_id="p", asset_id="a") + assert job.created_at.tzinfo is not None + assert job.updated_at.tzinfo is not None diff --git a/tests/unit/test_generated_video_domain.py b/tests/unit/test_generated_video_domain.py new file mode 100755 index 000000000..11da1f99b --- /dev/null +++ b/tests/unit/test_generated_video_domain.py @@ -0,0 +1,148 @@ +"""generated_video 领域模型单元测试.""" + +import pytest + +from domain.generated_video import GeneratedVideo + + +class TestGeneratedVideoCreate: + """GeneratedVideo.create 工厂方法测试.""" + + def test_create_with_required_fields(self): + video = GeneratedVideo.create( + project_id="proj_001", + generation_task_id="task_001", + name="测试视频", + file_url="https://example.com/out.mp4", + ) + assert video.id + assert len(video.id) == 32 + assert video.project_id == "proj_001" + assert video.generation_task_id == "task_001" + assert video.name == "测试视频" + assert video.file_url == "https://example.com/out.mp4" + # 默认值 + assert video.user_id == "" + assert video.file_size == 0 + assert video.duration == 0.0 + assert video.width == 0 + assert video.height == 0 + assert video.fps == 0.0 + assert video.thumbnail_url is None + assert video.status == "completed" + assert video.review_status == "pending_review" + assert video.generation_params == {} + assert video.video_fingerprint is None + assert video.is_duplicate is False + assert video.duplicate_of is None + assert video.generated_at is not None + assert video.created_at is not None + + def test_create_with_all_fields(self): + video = GeneratedVideo.create( + project_id="proj_002", + generation_task_id="task_002", + name="完整视频", + file_url="https://example.com/full.mp4", + user_id="user_001", + file_size=1024000, + duration=30.5, + width=1920, + height=1080, + fps=30.0, + thumbnail_url="https://example.com/thumb.jpg", + generation_params={"quality": "high"}, + ) + assert video.user_id == "user_001" + assert video.file_size == 1024000 + assert video.duration == 30.5 + assert video.width == 1920 + assert video.height == 1080 + assert video.fps == 30.0 + assert video.thumbnail_url == "https://example.com/thumb.jpg" + assert video.generation_params == {"quality": "high"} + + def test_create_strips_strings(self): + video = GeneratedVideo.create( + project_id=" proj_003 ", + generation_task_id=" task_003 ", + name=" 测试视频 ", + file_url=" https://example.com/out.mp4 ", + user_id=" user_003 ", + ) + assert video.project_id == "proj_003" + assert video.generation_task_id == "task_003" + assert video.name == "测试视频" + assert video.file_url == "https://example.com/out.mp4" + assert video.user_id == "user_003" + + def test_create_empty_project_id_raises(self): + with pytest.raises(ValueError, match="project_id"): + GeneratedVideo.create( + project_id="", + generation_task_id="t", + name="n", + file_url="u", + ) + + def test_create_whitespace_project_id_raises(self): + with pytest.raises(ValueError, match="project_id"): + GeneratedVideo.create( + project_id=" ", + generation_task_id="t", + name="n", + file_url="u", + ) + + def test_create_empty_generation_task_id_raises(self): + with pytest.raises(ValueError, match="generation_task_id"): + GeneratedVideo.create( + project_id="p", + generation_task_id="", + name="n", + file_url="u", + ) + + def test_create_empty_name_raises(self): + with pytest.raises(ValueError, match="name"): + GeneratedVideo.create( + project_id="p", + generation_task_id="t", + name="", + file_url="u", + ) + + def test_create_empty_file_url_raises(self): + with pytest.raises(ValueError, match="file_url"): + GeneratedVideo.create( + project_id="p", + generation_task_id="t", + name="n", + file_url="", + ) + + def test_create_none_generation_params_defaults_to_empty_dict(self): + video = GeneratedVideo.create( + project_id="p", + generation_task_id="t", + name="n", + file_url="u", + generation_params=None, + ) + assert video.generation_params == {} + + def test_create_ids_are_unique(self): + v1 = GeneratedVideo.create( + project_id="p", generation_task_id="t1", name="n1", file_url="u1" + ) + v2 = GeneratedVideo.create( + project_id="p", generation_task_id="t2", name="n2", file_url="u2" + ) + assert v1.id != v2.id + + def test_create_timestamps_are_utc(self): + video = GeneratedVideo.create( + project_id="p", generation_task_id="t", name="n", file_url="u" + ) + assert video.created_at.tzinfo is not None + assert video.generated_at.tzinfo is not None