diff --git a/tests/unit/test_duplication.py b/tests/unit/test_duplication.py index a24c7e5b0..86672ef57 100755 --- a/tests/unit/test_duplication.py +++ b/tests/unit/test_duplication.py @@ -112,32 +112,44 @@ class TestDuplicateSegmentCreate: def test_create_similarity_boundary_values(self): # 0 和 100 都是合法的 seg0 = DuplicateSegment.create( - source_start=0.0, source_end=1.0, - matched_video_id="v1", matched_video_name="v", - matched_start=0.0, matched_end=1.0, + source_start=0.0, + source_end=1.0, + matched_video_id="v1", + matched_video_name="v", + matched_start=0.0, + matched_end=1.0, similarity=0.0, ) assert seg0.similarity == 0.0 seg100 = DuplicateSegment.create( - source_start=0.0, source_end=1.0, - matched_video_id="v1", matched_video_name="v", - matched_start=0.0, matched_end=1.0, + source_start=0.0, + source_end=1.0, + matched_video_id="v1", + matched_video_name="v", + matched_start=0.0, + matched_end=1.0, similarity=100.0, ) assert seg100.similarity == 100.0 def test_create_unique_ids(self): seg1 = DuplicateSegment.create( - source_start=0.0, source_end=1.0, - matched_video_id="v1", matched_video_name="v", - matched_start=0.0, matched_end=1.0, + source_start=0.0, + source_end=1.0, + matched_video_id="v1", + matched_video_name="v", + matched_start=0.0, + matched_end=1.0, similarity=50.0, ) seg2 = DuplicateSegment.create( - source_start=0.0, source_end=1.0, - matched_video_id="v1", matched_video_name="v", - matched_start=0.0, matched_end=1.0, + source_start=0.0, + source_end=1.0, + matched_video_id="v1", + matched_video_name="v", + matched_start=0.0, + matched_end=1.0, similarity=50.0, ) assert seg1.id != seg2.id @@ -213,20 +225,19 @@ class TestDuplicationRecordCreate: class TestDuplicationRecordStatus: def test_mark_processing(self): - record = DuplicationRecord.create( - user_id="u1", filename="t.mp4", file_size=100, storage_key="k1" - ) + record = DuplicationRecord.create(user_id="u1", filename="t.mp4", file_size=100, storage_key="k1") record.mark_processing() assert record.status == "processing" def test_mark_completed(self): - record = DuplicationRecord.create( - user_id="u1", filename="t.mp4", file_size=100, storage_key="k1" - ) + record = DuplicationRecord.create(user_id="u1", filename="t.mp4", file_size=100, storage_key="k1") seg = DuplicateSegment.create( - source_start=0.0, source_end=5.0, - matched_video_id="v1", matched_video_name="v", - matched_start=0.0, matched_end=5.0, + source_start=0.0, + source_end=5.0, + matched_video_id="v1", + matched_video_name="v", + matched_start=0.0, + matched_end=5.0, similarity=90.0, ) record.mark_completed(duplicate_rate=25.5, duplicate_count=3, segments=[seg]) @@ -236,26 +247,20 @@ class TestDuplicationRecordStatus: assert len(record.segments) == 1 def test_mark_completed_invalid_rate_raises(self): - record = DuplicationRecord.create( - user_id="u1", filename="t.mp4", file_size=100, storage_key="k1" - ) + record = DuplicationRecord.create(user_id="u1", filename="t.mp4", file_size=100, storage_key="k1") with pytest.raises(ValueError, match="duplicate_rate must be between 0 and 100"): record.mark_completed(duplicate_rate=-1, duplicate_count=0, segments=[]) with pytest.raises(ValueError, match="duplicate_rate must be between 0 and 100"): record.mark_completed(duplicate_rate=101, duplicate_count=0, segments=[]) def test_mark_failed(self): - record = DuplicationRecord.create( - user_id="u1", filename="t.mp4", file_size=100, storage_key="k1" - ) + record = DuplicationRecord.create(user_id="u1", filename="t.mp4", file_size=100, storage_key="k1") record.mark_failed("网络超时") assert record.status == "failed" assert record.error_message == "网络超时" def test_can_retry_only_failed(self): - record = DuplicationRecord.create( - user_id="u1", filename="t.mp4", file_size=100, storage_key="k1" - ) + record = DuplicationRecord.create(user_id="u1", filename="t.mp4", file_size=100, storage_key="k1") assert record.can_retry() is False # pending record.mark_processing() @@ -265,25 +270,27 @@ class TestDuplicationRecordStatus: assert record.can_retry() is True # failed seg = DuplicateSegment.create( - source_start=0.0, source_end=1.0, - matched_video_id="v1", matched_video_name="v", - matched_start=0.0, matched_end=1.0, + source_start=0.0, + source_end=1.0, + matched_video_id="v1", + matched_video_name="v", + matched_start=0.0, + matched_end=1.0, similarity=50.0, ) - record2 = DuplicationRecord.create( - user_id="u1", filename="t.mp4", file_size=100, storage_key="k1" - ) + record2 = DuplicationRecord.create(user_id="u1", filename="t.mp4", file_size=100, storage_key="k1") record2.mark_completed(10.0, 1, [seg]) assert record2.can_retry() is False # completed def test_reset_for_retry(self): - record = DuplicationRecord.create( - user_id="u1", filename="t.mp4", file_size=100, storage_key="k1" - ) + record = DuplicationRecord.create(user_id="u1", filename="t.mp4", file_size=100, storage_key="k1") seg = DuplicateSegment.create( - source_start=0.0, source_end=1.0, - matched_video_id="v1", matched_video_name="v", - matched_start=0.0, matched_end=1.0, + source_start=0.0, + source_end=1.0, + matched_video_id="v1", + matched_video_name="v", + matched_start=0.0, + matched_end=1.0, similarity=50.0, ) record.mark_completed(50.0, 2, [seg]) diff --git a/tests/unit/test_edit_plan_clip.py b/tests/unit/test_edit_plan_clip.py index 81e683e0c..f118b5437 100755 --- a/tests/unit/test_edit_plan_clip.py +++ b/tests/unit/test_edit_plan_clip.py @@ -140,15 +140,11 @@ class TestEditPlanClipStateTransitions: class TestEditPlanClipProperties: def test_end_time(self): - clip = EditPlanClip.create( - plan_id="p1", clip_type="v", order=1, start_time=10.0, duration=5.0 - ) + clip = EditPlanClip.create(plan_id="p1", clip_type="v", order=1, start_time=10.0, duration=5.0) assert clip.end_time == 15.0 def test_end_time_zero_duration(self): - clip = EditPlanClip.create( - plan_id="p1", clip_type="v", order=1, start_time=5.0, duration=0.0 - ) + clip = EditPlanClip.create(plan_id="p1", clip_type="v", order=1, start_time=5.0, duration=0.0) assert clip.end_time == 5.0 def test_has_asset_true(self): diff --git a/tests/unit/test_subtitle.py b/tests/unit/test_subtitle.py index 2da0940ba..c8bac484a 100755 --- a/tests/unit/test_subtitle.py +++ b/tests/unit/test_subtitle.py @@ -2,7 +2,7 @@ import pytest -from packages.domain.subtitle import SubtitleWord, SubtitleSegment, SubtitleTimeline +from packages.domain.subtitle import SubtitleSegment, SubtitleTimeline, SubtitleWord class TestSubtitleWord: @@ -46,26 +46,32 @@ class TestSubtitleTimeline: assert tl.total_duration == 0.0 def test_segment_count(self): - tl = SubtitleTimeline(segments=[ - SubtitleSegment(text="第一段", start=0.0, end=2.0), - SubtitleSegment(text="第二段", start=2.0, end=5.0), - ]) + tl = SubtitleTimeline( + segments=[ + SubtitleSegment(text="第一段", start=0.0, end=2.0), + SubtitleSegment(text="第二段", start=2.0, end=5.0), + ] + ) assert tl.segment_count == 2 assert tl.total_chars == 6 def test_total_chars(self): - tl = SubtitleTimeline(segments=[ - SubtitleSegment(text="abc", start=0, end=1), - SubtitleSegment(text="defg", start=1, end=2), - ]) + tl = SubtitleTimeline( + segments=[ + SubtitleSegment(text="abc", start=0, end=1), + SubtitleSegment(text="defg", start=1, end=2), + ] + ) assert tl.total_chars == 7 class TestMergeShortSegments: def test_single_segment_no_change(self): - tl = SubtitleTimeline(segments=[ - SubtitleSegment(text="你好", start=0.0, end=1.0), - ]) + tl = SubtitleTimeline( + segments=[ + SubtitleSegment(text="你好", start=0.0, end=1.0), + ] + ) result = tl.merge_short_segments(min_chars=8) assert result.segment_count == 1 assert result.segments[0].text == "你好" @@ -76,12 +82,14 @@ class TestMergeShortSegments: assert result.segment_count == 0 def test_merge_short_segments(self): - tl = SubtitleTimeline(segments=[ - SubtitleSegment(text="你好", start=0.0, end=1.0), - SubtitleSegment(text="今天", start=1.0, end=2.0), - SubtitleSegment(text="天气", start=2.0, end=3.0), - SubtitleSegment(text="真好", start=3.0, end=4.0), - ]) + tl = SubtitleTimeline( + segments=[ + SubtitleSegment(text="你好", start=0.0, end=1.0), + SubtitleSegment(text="今天", start=1.0, end=2.0), + SubtitleSegment(text="天气", start=2.0, end=3.0), + SubtitleSegment(text="真好", start=3.0, end=4.0), + ] + ) result = tl.merge_short_segments(min_chars=4) # 每段2字,min=4,应该每2段合并 assert result.segment_count == 2 @@ -94,26 +102,40 @@ class TestMergeShortSegments: def test_remaining_merged_to_last(self): # 3段,每段2字,min=5 → 前5字合并,剩余1字并到最后 - tl = SubtitleTimeline(segments=[ - SubtitleSegment(text="一二", start=0, end=1), - SubtitleSegment(text="三四", start=1, end=2), - SubtitleSegment(text="五", start=2, end=3), - ]) + tl = SubtitleTimeline( + segments=[ + SubtitleSegment(text="一二", start=0, end=1), + SubtitleSegment(text="三四", start=1, end=2), + SubtitleSegment(text="五", start=2, end=3), + ] + ) result = tl.merge_short_segments(min_chars=5) assert result.segment_count == 1 assert result.segments[0].text == "一二三四五" def test_merge_with_words(self): - tl = SubtitleTimeline(segments=[ - SubtitleSegment(text="你好", start=0.0, end=1.0, words=[ - SubtitleWord(text="你", start=0.0, end=0.5), - SubtitleWord(text="好", start=0.5, end=1.0), - ]), - SubtitleSegment(text="世界", start=1.0, end=2.0, words=[ - SubtitleWord(text="世", start=1.0, end=1.5), - SubtitleWord(text="界", start=1.5, end=2.0), - ]), - ]) + tl = SubtitleTimeline( + segments=[ + SubtitleSegment( + text="你好", + start=0.0, + end=1.0, + words=[ + SubtitleWord(text="你", start=0.0, end=0.5), + SubtitleWord(text="好", start=0.5, end=1.0), + ], + ), + SubtitleSegment( + text="世界", + start=1.0, + end=2.0, + words=[ + SubtitleWord(text="世", start=1.0, end=1.5), + SubtitleWord(text="界", start=1.5, end=2.0), + ], + ), + ] + ) result = tl.merge_short_segments(min_chars=10) assert result.segment_count == 1 assert len(result.segments[0].words) == 4 @@ -121,26 +143,32 @@ class TestMergeShortSegments: class TestSplitLongSegments: def test_short_segments_no_split(self): - tl = SubtitleTimeline(segments=[ - SubtitleSegment(text="短文本", start=0.0, end=1.0), - ]) + tl = SubtitleTimeline( + segments=[ + SubtitleSegment(text="短文本", start=0.0, end=1.0), + ] + ) result = tl.split_long_segments(max_chars=20) assert result.segment_count == 1 def test_split_by_punctuation(self): text = "今天天气真好。我们出去玩吧!" - tl = SubtitleTimeline(segments=[ - SubtitleSegment(text=text, start=0.0, end=5.0), - ]) + tl = SubtitleTimeline( + segments=[ + SubtitleSegment(text=text, start=0.0, end=5.0), + ] + ) result = tl.split_long_segments(max_chars=10) assert result.segment_count >= 2 # 合并起来应该等于原文 assert "".join(s.text for s in result.segments) == text def test_split_preserves_time_order(self): - tl = SubtitleTimeline(segments=[ - SubtitleSegment(text="一二三四五六七八九十。十一二三四五六七八九十。", start=0.0, end=10.0), - ]) + tl = SubtitleTimeline( + segments=[ + SubtitleSegment(text="一二三四五六七八九十。十一二三四五六七八九十。", start=0.0, end=10.0), + ] + ) result = tl.split_long_segments(max_chars=10) # 时间应该是递增的 for i in range(len(result.segments) - 1): diff --git a/tests/unit/test_tts_config.py b/tests/unit/test_tts_config.py index 962531ac8..3586d2080 100755 --- a/tests/unit/test_tts_config.py +++ b/tests/unit/test_tts_config.py @@ -40,16 +40,18 @@ class TestTtsConfigParse: assert config.speed == 1.0 def test_parse_enabled_true_with_all_fields(self): - config = TtsConfig.parse({ - "enabled": True, - "voice_id": "female_warm", - "speed": 1.5, - "pitch": 2.0, - "volume": 0.9, - "text": "你好世界", - "align_mode": "subtitle", - "overlap_mode": "mix", - }) + config = TtsConfig.parse( + { + "enabled": True, + "voice_id": "female_warm", + "speed": 1.5, + "pitch": 2.0, + "volume": 0.9, + "text": "你好世界", + "align_mode": "subtitle", + "overlap_mode": "mix", + } + ) assert config.enabled is True assert config.voice_id == "female_warm" assert config.speed == 1.5 diff --git a/tests/unit/test_verification_code.py b/tests/unit/test_verification_code.py index ec897e05f..73a6c8a70 100755 --- a/tests/unit/test_verification_code.py +++ b/tests/unit/test_verification_code.py @@ -64,6 +64,7 @@ class TestVerificationCodeStatus: code = VerificationCode.create(recipient="test@example.com", code_type="email_bind", ttl_seconds=0) # 0秒TTL,立即可能过期(有极小概率因时间差没过) import time + time.sleep(0.01) assert code.is_expired is True assert code.is_valid is False