7e505a04c7
CI/CD Pipeline / Check if frontend-only change (push) Has been cancelled
CI/CD Pipeline / Validate - Code Quality (push) Has been cancelled
CI/CD Pipeline / Validate - Type Check (mypy) (push) Has been cancelled
CI/CD Pipeline / Validate - Migration (alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Build Staging API Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
148 lines
4.8 KiB
Python
Executable File
148 lines
4.8 KiB
Python
Executable File
"""文本分段工具单元测试."""
|
|
|
|
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
|