1. 删除了 test/unit/external_systems/framework/ 下的废弃空测试目录 2. 修复多处测试断言逻辑、参数传递与测试数据构造 3. 新增日志级别、缓存令牌、流事件等DTO单元测试 4. 补充路由绑定、会话仓储、outbox仓储的测试覆盖 5. 更新测试用例中的异常类型、参数校验与业务逻辑断言
116 lines
3.6 KiB
Python
116 lines
3.6 KiB
Python
"""truncation.py DTO 单元测试。
|
|
|
|
覆盖 ``TruncationCandidate`` 与 ``TruncationResult`` 的字段赋值、默认值、
|
|
不可变语义与 ``__post_init__`` 校验逻辑。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import dataclasses
|
|
|
|
import pytest
|
|
from yuxi.channels.contract.dtos.truncation import (
|
|
TruncationCandidate,
|
|
TruncationResult,
|
|
)
|
|
from yuxi.channels.contract.errors import ValidationError
|
|
|
|
pytestmark = pytest.mark.unit
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestTruncationCandidate:
|
|
"""截断候选 DTO 测试。"""
|
|
|
|
def test_fields_are_assigned(self):
|
|
# Arrange
|
|
# Act
|
|
candidate = TruncationCandidate(text="hello", source="user_message", length=5)
|
|
# Assert
|
|
assert candidate.text == "hello"
|
|
assert candidate.source == "user_message"
|
|
assert candidate.length == 5
|
|
|
|
def test_zero_length_is_valid(self):
|
|
# Arrange
|
|
# Act
|
|
candidate = TruncationCandidate(text="hello", source="user_message", length=0)
|
|
# Assert - length 为 0 是合法的(非负)
|
|
assert candidate.length == 0
|
|
|
|
def test_is_frozen(self):
|
|
# Arrange
|
|
candidate = TruncationCandidate(text="hello", source="user_message", length=5)
|
|
# Act / Assert
|
|
with pytest.raises(dataclasses.FrozenInstanceError):
|
|
candidate.text = "other" # type: ignore[misc]
|
|
|
|
def test_empty_text_raises_validation_error(self):
|
|
# Arrange
|
|
# Act / Assert
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
TruncationCandidate(text="", source="user_message", length=5)
|
|
assert exc_info.value.field == "text"
|
|
|
|
def test_empty_source_raises_validation_error(self):
|
|
# Arrange
|
|
# Act / Assert
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
TruncationCandidate(text="hello", source="", length=5)
|
|
assert exc_info.value.field == "source"
|
|
|
|
def test_negative_length_raises_validation_error(self):
|
|
# Arrange
|
|
# Act / Assert
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
TruncationCandidate(text="hello", source="user_message", length=-1)
|
|
assert exc_info.value.field == "length"
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestTruncationResult:
|
|
"""截断结果 DTO 测试。"""
|
|
|
|
def test_required_fields_are_assigned(self):
|
|
# Arrange
|
|
# Act
|
|
result = TruncationResult(is_truncated=True)
|
|
# Assert
|
|
assert result.is_truncated is True
|
|
|
|
def test_defaults_are_correct(self):
|
|
# Arrange
|
|
# Act
|
|
result = TruncationResult(is_truncated=False)
|
|
# Assert
|
|
assert result.missing_content is None
|
|
assert result.fallback_to_persistent is False
|
|
assert result.completed_text is None
|
|
assert result.original_length is None
|
|
assert result.completed_length is None
|
|
|
|
def test_custom_values_are_assigned(self):
|
|
# Arrange
|
|
# Act
|
|
result = TruncationResult(
|
|
is_truncated=True,
|
|
missing_content="missing",
|
|
fallback_to_persistent=True,
|
|
completed_text="completed",
|
|
original_length=100,
|
|
completed_length=150,
|
|
)
|
|
# Assert
|
|
assert result.missing_content == "missing"
|
|
assert result.fallback_to_persistent is True
|
|
assert result.completed_text == "completed"
|
|
assert result.original_length == 100
|
|
assert result.completed_length == 150
|
|
|
|
def test_is_frozen(self):
|
|
# Arrange
|
|
result = TruncationResult(is_truncated=True)
|
|
# Act / Assert
|
|
with pytest.raises(dataclasses.FrozenInstanceError):
|
|
result.is_truncated = False # type: ignore[misc]
|