#!/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)