v9.5: 實作標籤完全不重疊算法
- 新增 _calculate_lane_conflicts_v2() 分開返回標籤重疊和線穿框分數 - 修改泳道選擇算法,優先選擇無標籤重疊的泳道 - 兩階段搜尋:優先側別無可用泳道則嘗試另一側 - 增強日誌輸出,顯示標籤範圍和詳細衝突分數 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
146
tests/unit/test_schemas.py
Normal file
146
tests/unit/test_schemas.py
Normal file
@@ -0,0 +1,146 @@
|
||||
"""
|
||||
資料模型測試
|
||||
|
||||
測試 Pydantic schemas 的基本驗證功能
|
||||
|
||||
Version: 1.0.0
|
||||
DocID: TDD-UT-SCHEMA-001
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from datetime import datetime
|
||||
from backend.schemas import Event, EventType, TimelineConfig, ExportOptions, ExportFormat
|
||||
|
||||
|
||||
class TestEventModel:
|
||||
"""Event 模型測試"""
|
||||
|
||||
def test_create_valid_event(self):
|
||||
"""測試建立有效事件"""
|
||||
event = Event(
|
||||
id="test-001",
|
||||
title="測試事件",
|
||||
start=datetime(2024, 1, 1, 9, 0, 0),
|
||||
end=datetime(2024, 1, 1, 17, 0, 0),
|
||||
group="Phase 1",
|
||||
description="這是一個測試事件",
|
||||
color="#3B82F6",
|
||||
event_type=EventType.RANGE
|
||||
)
|
||||
|
||||
assert event.id == "test-001"
|
||||
assert event.title == "測試事件"
|
||||
assert event.group == "Phase 1"
|
||||
assert event.color == "#3B82F6"
|
||||
|
||||
def test_event_end_before_start_validation(self):
|
||||
"""測試結束時間早於開始時間的驗證"""
|
||||
with pytest.raises(ValueError, match="結束時間必須晚於開始時間"):
|
||||
Event(
|
||||
id="test-002",
|
||||
title="無效事件",
|
||||
start=datetime(2024, 1, 2, 9, 0, 0),
|
||||
end=datetime(2024, 1, 1, 9, 0, 0), # 結束早於開始
|
||||
)
|
||||
|
||||
def test_event_with_invalid_color(self):
|
||||
"""測試無效的顏色格式"""
|
||||
with pytest.raises(ValueError):
|
||||
Event(
|
||||
id="test-003",
|
||||
title="測試事件",
|
||||
start=datetime(2024, 1, 1, 9, 0, 0),
|
||||
color="invalid-color" # 無效的顏色格式
|
||||
)
|
||||
|
||||
def test_event_optional_fields(self):
|
||||
"""測試可選欄位"""
|
||||
event = Event(
|
||||
id="test-004",
|
||||
title="最小事件",
|
||||
start=datetime(2024, 1, 1, 9, 0, 0)
|
||||
)
|
||||
|
||||
assert event.end is None
|
||||
assert event.group is None
|
||||
assert event.description is None
|
||||
assert event.color is None
|
||||
|
||||
|
||||
class TestTimelineConfig:
|
||||
"""TimelineConfig 模型測試"""
|
||||
|
||||
def test_default_config(self):
|
||||
"""測試預設配置"""
|
||||
config = TimelineConfig()
|
||||
|
||||
assert config.direction == 'horizontal'
|
||||
assert config.theme.value == 'modern'
|
||||
assert config.show_grid is True
|
||||
assert config.show_tooltip is True
|
||||
|
||||
def test_custom_config(self):
|
||||
"""測試自訂配置"""
|
||||
config = TimelineConfig(
|
||||
direction='vertical',
|
||||
theme='classic',
|
||||
show_grid=False
|
||||
)
|
||||
|
||||
assert config.direction == 'vertical'
|
||||
assert config.theme.value == 'classic'
|
||||
assert config.show_grid is False
|
||||
|
||||
|
||||
class TestExportOptions:
|
||||
"""ExportOptions 模型測試"""
|
||||
|
||||
def test_valid_export_options(self):
|
||||
"""測試有效的匯出選項"""
|
||||
options = ExportOptions(
|
||||
fmt=ExportFormat.PDF,
|
||||
dpi=300,
|
||||
width=1920,
|
||||
height=1080
|
||||
)
|
||||
|
||||
assert options.fmt == ExportFormat.PDF
|
||||
assert options.dpi == 300
|
||||
assert options.width == 1920
|
||||
assert options.height == 1080
|
||||
|
||||
def test_dpi_range_validation(self):
|
||||
"""測試 DPI 範圍驗證"""
|
||||
# DPI 太低
|
||||
with pytest.raises(ValueError):
|
||||
ExportOptions(
|
||||
fmt=ExportFormat.PNG,
|
||||
dpi=50 # < 72
|
||||
)
|
||||
|
||||
# DPI 太高
|
||||
with pytest.raises(ValueError):
|
||||
ExportOptions(
|
||||
fmt=ExportFormat.PNG,
|
||||
dpi=700 # > 600
|
||||
)
|
||||
|
||||
def test_dimension_validation(self):
|
||||
"""測試尺寸範圍驗證"""
|
||||
# 寬度太小
|
||||
with pytest.raises(ValueError):
|
||||
ExportOptions(
|
||||
fmt=ExportFormat.PNG,
|
||||
width=500 # < 800
|
||||
)
|
||||
|
||||
# 高度太大
|
||||
with pytest.raises(ValueError):
|
||||
ExportOptions(
|
||||
fmt=ExportFormat.PNG,
|
||||
height=5000 # > 4096
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
Reference in New Issue
Block a user