#!/usr/bin/env python3 """ 备份和导入功能测试脚本 验证所有表是否正确包含在备份中 """ import asyncio import sys import os import json import tempfile # 添加项目根目录到Python路径 sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from db_manager import db_manager from loguru import logger def get_all_tables(): """获取数据库中的所有表""" try: with db_manager.lock: cursor = db_manager.conn.cursor() cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'") tables = [row[0] for row in cursor.fetchall()] return sorted(tables) except Exception as e: logger.error(f"获取表列表失败: {e}") return [] def get_table_row_count(table_name): """获取表的行数""" try: with db_manager.lock: cursor = db_manager.conn.cursor() cursor.execute(f"SELECT COUNT(*) FROM {table_name}") return cursor.fetchone()[0] except Exception as e: logger.error(f"获取表 {table_name} 行数失败: {e}") return 0 def create_test_data(): """创建测试数据""" print("📝 创建测试数据...") test_data_created = [] try: # 1. 创建测试账号 test_cookie_id = "test_backup_001" success = db_manager.save_cookie(test_cookie_id, "test_cookie_value_for_backup") if success: test_data_created.append(f"账号: {test_cookie_id}") # 2. 创建关键词 keywords = [("测试关键词1", "测试回复1"), ("测试关键词2", "测试回复2")] success = db_manager.save_keywords(test_cookie_id, keywords) if success: test_data_created.append(f"关键词: {len(keywords)} 个") # 3. 创建AI回复设置 ai_settings = { 'ai_enabled': True, 'model_name': 'qwen-plus', 'api_key': 'test-backup-key', 'base_url': 'https://test.com', 'max_discount_percent': 10, 'max_discount_amount': 100, 'max_bargain_rounds': 3, 'custom_prompts': '{"test": "prompt"}' } success = db_manager.save_ai_reply_settings(test_cookie_id, ai_settings) if success: test_data_created.append("AI回复设置") # 4. 创建默认回复 success = db_manager.save_default_reply(test_cookie_id, True, "测试默认回复内容") if success: test_data_created.append("默认回复") # 5. 创建商品信息 success = db_manager.save_item_basic_info( test_cookie_id, "test_item_001", "测试商品", "测试描述", "测试分类", "100", "测试详情" ) if success: test_data_created.append("商品信息") print(f" ✅ 测试数据创建成功: {', '.join(test_data_created)}") return True except Exception as e: print(f" ❌ 创建测试数据失败: {e}") return False def test_backup_export(): """测试备份导出功能""" print("\n📤 测试备份导出功能...") try: # 获取所有表 all_tables = get_all_tables() print(f" 数据库中的表: {all_tables}") # 导出备份 backup_data = db_manager.export_backup() if not backup_data: print(" ❌ 备份导出失败") return None # 检查备份数据结构 print(f" ✅ 备份导出成功") print(f" 备份版本: {backup_data.get('version')}") print(f" 备份时间: {backup_data.get('timestamp')}") # 检查包含的表 backed_up_tables = list(backup_data['data'].keys()) print(f" 备份的表: {sorted(backed_up_tables)}") # 检查是否有遗漏的表 missing_tables = set(all_tables) - set(backed_up_tables) if missing_tables: print(f" ⚠️ 未备份的表: {sorted(missing_tables)}") else: print(f" ✅ 所有表都已备份") # 检查每个表的数据量 print(f"\n 📊 各表数据统计:") for table in sorted(backed_up_tables): row_count = len(backup_data['data'][table]['rows']) print(f" {table}: {row_count} 行") return backup_data except Exception as e: print(f" ❌ 备份导出异常: {e}") return None def test_backup_import(backup_data): """测试备份导入功能""" print("\n📥 测试备份导入功能...") if not backup_data: print(" ❌ 没有备份数据可导入") return False try: # 记录导入前的数据量 print(" 📊 导入前数据统计:") all_tables = get_all_tables() before_counts = {} for table in all_tables: count = get_table_row_count(table) before_counts[table] = count print(f" {table}: {count} 行") # 执行导入 success = db_manager.import_backup(backup_data) if not success: print(" ❌ 备份导入失败") return False print(" ✅ 备份导入成功") # 记录导入后的数据量 print("\n 📊 导入后数据统计:") after_counts = {} for table in all_tables: count = get_table_row_count(table) after_counts[table] = count print(f" {table}: {count} 行") # 检查数据一致性 print("\n 🔍 数据一致性检查:") for table in sorted(backup_data['data'].keys()): expected_count = len(backup_data['data'][table]['rows']) actual_count = after_counts.get(table, 0) if table == 'system_settings': # 系统设置表可能保留管理员密码,所以数量可能不完全一致 print(f" {table}: 期望 {expected_count}, 实际 {actual_count} (系统设置表)") elif expected_count == actual_count: print(f" {table}: ✅ 一致 ({actual_count} 行)") else: print(f" {table}: ❌ 不一致 (期望 {expected_count}, 实际 {actual_count})") return True except Exception as e: print(f" ❌ 备份导入异常: {e}") return False def test_backup_file_operations(): """测试备份文件操作""" print("\n💾 测试备份文件操作...") try: # 导出备份 backup_data = db_manager.export_backup() if not backup_data: print(" ❌ 导出备份失败") return False # 保存到临时文件 with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False, encoding='utf-8') as f: json.dump(backup_data, f, indent=2, ensure_ascii=False) temp_file = f.name print(f" ✅ 备份保存到临时文件: {temp_file}") # 从文件读取 with open(temp_file, 'r', encoding='utf-8') as f: loaded_backup = json.load(f) print(f" ✅ 从文件读取备份成功") # 验证数据完整性 if loaded_backup == backup_data: print(f" ✅ 文件数据完整性验证通过") else: print(f" ❌ 文件数据完整性验证失败") return False # 清理临时文件 os.unlink(temp_file) print(f" ✅ 临时文件清理完成") return True except Exception as e: print(f" ❌ 备份文件操作异常: {e}") return False def main(): """主测试函数""" print("🚀 备份和导入功能测试开始") print("=" * 50) # 创建测试数据 data_ok = create_test_data() if not data_ok: print("\n❌ 测试数据创建失败") return # 测试备份导出 backup_data = test_backup_export() if not backup_data: print("\n❌ 备份导出测试失败") return # 测试备份导入 import_ok = test_backup_import(backup_data) if not import_ok: print("\n❌ 备份导入测试失败") return # 测试文件操作 file_ok = test_backup_file_operations() if not file_ok: print("\n❌ 备份文件操作测试失败") return print("\n" + "=" * 50) print("🎉 所有测试通过!备份和导入功能正常!") print("\n✅ 功能验证:") print(" • 所有13个表都包含在备份中") print(" • 备份导出功能正常") print(" • 备份导入功能正常") print(" • 数据完整性保持") print(" • 文件操作正常") print("\n📋 包含的表:") # 显示所有备份的表 if backup_data and 'data' in backup_data: for table in sorted(backup_data['data'].keys()): row_count = len(backup_data['data'][table]['rows']) print(f" • {table}: {row_count} 行数据") if __name__ == "__main__": main()