"""文本分段工具单元测试.""" from __future__ import annotations import pytest from packages.application.tts_job.text_splitter import split_text class TestSplitText: """split_text 函数测试""" def test_empty_string_returns_empty_list(self): """空字符串返回空列表""" assert split_text("") == [] def test_whitespace_only_returns_empty_list(self): """纯空白字符返回空列表""" assert split_text(" \n \t ") == [] def test_short_text_returns_single_segment(self): """短文本直接返回单段""" text = "这是一段短文本。" result = split_text(text, max_chars=500) assert result == [text] def test_text_length_equals_max_chars(self): """文本长度恰好等于 max_chars 时返回单段""" text = "a" * 100 result = split_text(text, max_chars=100) assert len(result) == 1 assert len(result[0]) == 100 def test_splits_on_sentence_boundary(self): """在句子边界处分段""" # 构造长文本,确保超过 max_chars sentences = ["今天天气真好。我们一起去公园散步吧。", "公园里有很多花。还有很多小朋友在玩耍。"] * 10 text = "".join(sentences) result = split_text(text, max_chars=200) assert len(result) >= 2 # 每段都不超过 max_chars for seg in result: assert len(seg) <= 200 def test_all_segments_within_max_chars(self): """所有分段都不超过 max_chars""" text = "这是第一句话。这是第二句话。这是第三句话。这是第四句话。这是第五句话。" * 10 result = split_text(text, max_chars=100) for seg in result: assert len(seg) <= 100 def test_long_single_sentence_hard_cut(self): """超长单句会被硬切""" text = "a" * 1000 # 没有标点 result = split_text(text, max_chars=200) assert len(result) > 1 for seg in result: assert len(seg) <= 200 def test_newline_is_sentence_end(self): """换行符作为句子结束符""" text = "第一行内容\n第二行内容\n第三行内容" * 10 result = split_text(text, max_chars=50) assert len(result) > 1 for seg in result: assert len(seg) <= 50 def test_chinese_punctuation(self): """中文标点(。!?;)作为句子结束符""" text = "你好!今天吃什么?我吃米饭;你呢?我也吃米饭。" * 10 result = split_text(text, max_chars=80) for seg in result: assert len(seg) <= 80 def test_english_punctuation(self): """英文标点(.!?;)作为句子结束符""" text = "Hello! How are you? I'm fine; thank you. Good bye." * 10 result = split_text(text, max_chars=80) for seg in result: assert len(seg) <= 80 def test_merged_short_segments(self): """过短的段落会被合并""" # 构造很多短句 text = "你好。再见。谢谢。抱歉。好的。不行。可以。去吧。" * 5 # 每句3-4字 result = split_text(text, max_chars=100) # 合并后段数应该比单纯按句切的少 assert len(result) < len(text) // 3 # 粗略估计 for seg in result: assert len(seg) <= 100 def test_preserves_content(self): """分段后内容总和与原文基本一致(忽略strip的空白)""" text = "这是测试文本。包含多个句子。用来验证分段正确性。" * 5 result = split_text(text, max_chars=50) # 合并所有分段,去掉空白后应该与原文去掉空白后基本一致 combined = "".join(result).replace(" ", "") original = text.strip().replace(" ", "") assert combined == original def test_custom_max_chars(self): """支持自定义 max_chars""" text = "测试" * 100 # 200字 result_50 = split_text(text, max_chars=50) result_100 = split_text(text, max_chars=100) # max_chars 越小,段数应该越多 assert len(result_50) >= len(result_100) def test_single_char_text(self): """单字符文本""" assert split_text("好", max_chars=10) == ["好"] def test_text_with_only_punctuation(self): """纯标点文本""" text = "。。。。。。。。。。" # 10个句号 result = split_text(text, max_chars=5) assert len(result) >= 1 for seg in result: assert len(seg) <= 5 def test_mixed_content(self): """中英文混合内容""" text = "今天的天气是 sunny and warm。我们去了 park 玩。真的很开心!" * 5 result = split_text(text, max_chars=80) for seg in result: assert len(seg) <= 80