Some checks failed
CD Pipeline / deploy (push) Failing after 59s
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml) - 部署模式: rsync Python 檔案至 188 → docker restart (volume mount) - Dockerfile/requirements 變動時自動重建 Docker image - 部署通知: Telegram (開始/成功/失敗) - 健康檢查: https://mo.wooo.work/health (最多 5 次重試) - 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
155 lines
5.0 KiB
Python
155 lines
5.0 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
AI History Service 單元測試
|
||
測試修復後的功能是否正確運作
|
||
"""
|
||
|
||
import sys
|
||
import os
|
||
import json
|
||
from datetime import datetime, timedelta
|
||
|
||
# 確保可以 import 專案模組
|
||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||
|
||
from services.ai_history_service import AIHistoryService, AITemplateService
|
||
|
||
|
||
def test_safe_json_dumps():
|
||
"""測試安全 JSON 序列化"""
|
||
print("\n=== 測試 _safe_json_dumps ===")
|
||
|
||
# 測試 None
|
||
result = AIHistoryService._safe_json_dumps(None)
|
||
assert result is None, f"None 應該返回 None,實際: {result}"
|
||
print("✓ None 處理正確")
|
||
|
||
# 測試正常列表
|
||
result = AIHistoryService._safe_json_dumps(["關鍵字1", "關鍵字2"])
|
||
assert result == '["關鍵字1", "關鍵字2"]', f"列表序列化失敗: {result}"
|
||
print("✓ 列表序列化正確")
|
||
|
||
# 測試空列表
|
||
result = AIHistoryService._safe_json_dumps([])
|
||
assert result == '[]', f"空列表序列化失敗: {result}"
|
||
print("✓ 空列表序列化正確")
|
||
|
||
# 測試字典
|
||
result = AIHistoryService._safe_json_dumps({"key": "value"})
|
||
assert result == '{"key": "value"}', f"字典序列化失敗: {result}"
|
||
print("✓ 字典序列化正確")
|
||
|
||
# 測試不可序列化物件(應該轉為字串)
|
||
class UnserializableObject:
|
||
pass
|
||
result = AIHistoryService._safe_json_dumps(UnserializableObject())
|
||
assert result is not None, "不可序列化物件應該被轉為字串"
|
||
print("✓ 不可序列化物件處理正確")
|
||
|
||
print("=== _safe_json_dumps 測試全部通過 ===")
|
||
|
||
|
||
def test_input_validation():
|
||
"""測試輸入驗證"""
|
||
print("\n=== 測試輸入驗證 ===")
|
||
|
||
# 模擬測試 get_history_list 的輸入驗證邏輯
|
||
def validate_pagination(page, per_page):
|
||
page = max(1, page)
|
||
per_page = max(1, min(100, per_page))
|
||
return page, per_page
|
||
|
||
# 測試負數頁碼
|
||
page, per_page = validate_pagination(-5, 20)
|
||
assert page == 1, f"負數頁碼應該被修正為 1,實際: {page}"
|
||
print("✓ 負數頁碼驗證正確")
|
||
|
||
# 測試零頁碼
|
||
page, per_page = validate_pagination(0, 20)
|
||
assert page == 1, f"零頁碼應該被修正為 1,實際: {page}"
|
||
print("✓ 零頁碼驗證正確")
|
||
|
||
# 測試每頁數量超出限制
|
||
page, per_page = validate_pagination(1, 500)
|
||
assert per_page == 100, f"每頁數量應該被限制為 100,實際: {per_page}"
|
||
print("✓ 每頁數量上限驗證正確")
|
||
|
||
# 測試每頁數量為零
|
||
page, per_page = validate_pagination(1, 0)
|
||
assert per_page == 1, f"每頁數量零應該被修正為 1,實際: {per_page}"
|
||
print("✓ 每頁數量下限驗證正確")
|
||
|
||
# 模擬測試 get_statistics 的 days 驗證邏輯
|
||
def validate_days(days):
|
||
return max(1, min(365, days))
|
||
|
||
# 測試負數天數
|
||
days = validate_days(-10)
|
||
assert days == 1, f"負數天數應該被修正為 1,實際: {days}"
|
||
print("✓ 負數天數驗證正確")
|
||
|
||
# 測試超大天數
|
||
days = validate_days(1000)
|
||
assert days == 365, f"超大天數應該被限制為 365,實際: {days}"
|
||
print("✓ 天數上限驗證正確")
|
||
|
||
print("=== 輸入驗證測試全部通過 ===")
|
||
|
||
|
||
def test_batch_delete_empty_list():
|
||
"""測試批次刪除空列表"""
|
||
print("\n=== 測試 batch_delete 空列表 ===")
|
||
|
||
result = AIHistoryService.batch_delete([])
|
||
assert result['success_count'] == 0, f"空列表刪除數應為 0,實際: {result['success_count']}"
|
||
assert result['failed_ids'] == [], f"空列表失敗 ID 應為空,實際: {result['failed_ids']}"
|
||
print("✓ 空列表處理正確")
|
||
|
||
print("=== batch_delete 空列表測試通過 ===")
|
||
|
||
|
||
def test_service_instantiation():
|
||
"""測試服務實例化"""
|
||
print("\n=== 測試服務實例化 ===")
|
||
|
||
# 測試可以正常 import 和使用
|
||
from services.ai_history_service import ai_history_service, ai_template_service
|
||
|
||
assert ai_history_service is not None, "ai_history_service 應該存在"
|
||
assert ai_template_service is not None, "ai_template_service 應該存在"
|
||
print("✓ 全域服務實例創建成功")
|
||
|
||
print("=== 服務實例化測試通過 ===")
|
||
|
||
|
||
def run_all_tests():
|
||
"""執行所有測試"""
|
||
print("=" * 50)
|
||
print("AI History Service 單元測試")
|
||
print("=" * 50)
|
||
|
||
try:
|
||
test_safe_json_dumps()
|
||
test_input_validation()
|
||
test_batch_delete_empty_list()
|
||
test_service_instantiation()
|
||
|
||
print("\n" + "=" * 50)
|
||
print("✅ 所有測試通過!")
|
||
print("=" * 50)
|
||
return True
|
||
except AssertionError as e:
|
||
print(f"\n❌ 測試失敗: {e}")
|
||
return False
|
||
except Exception as e:
|
||
print(f"\n❌ 測試異常: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
|
||
if __name__ == "__main__":
|
||
success = run_all_tests()
|
||
sys.exit(0 if success else 1)
|