#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Obsidian KB - 主流程集成测试脚本 测试完整流程:BV号 → 提取 → 处理 → 输出 使用测试配置,不执行Git同步 """ import os import sys import tempfile import shutil from pathlib import Path # 添加项目路径 sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from main_pipeline import MainPipeline from src.config import Config def create_test_config() -> Config: """ 创建测试配置 Returns: 配置对象 """ # 创建临时目录作为测试vault temp_dir = tempfile.mkdtemp(prefix='obsidian_kb_test_') vault_path = Path(temp_dir) / 'vault' vault_path.mkdir(parents=True, exist_ok=True) # 创建临时目录作为存储 storage_dir = Path(temp_dir) / 'storage' storage_dir.mkdir(parents=True, exist_ok=True) print(f"📁 测试目录: {temp_dir}") print(f"📁 测试Vault: {vault_path}") # 创建测试配置 test_config_dict = { 'ai': { 'provider': 'openai', 'model': 'gpt-4', 'api_key': None, # 测试时不使用AI }, 'storage': { 'inbox_dir': 'inbox', 'topics_dir': 'topics', 'data_dir': str(storage_dir), }, 'git': { 'enabled': False, # 测试时禁用Git 'vault_path': str(vault_path), 'remote': 'origin', 'branch': 'main', 'auto_push': False, 'commit_message_template': 'Add note: {title}', }, 'obsidian': { 'vault_path': str(vault_path), 'notes_folder': 'Notes', }, 'output': { 'organize_by': 'author', 'filename_format': '{date}_{title}.md', 'auto_tags': True, 'default_tags': ['video', 'bilibili', 'test'], }, 'sources': { 'bilibili': { 'enabled': True, 'cookie': None, 'extraction': { 'headless': True, 'timeout': 30, }, }, }, 'temp_dir': temp_dir, # 保存临时目录路径以便清理 } # 创建Config对象(手动设置配置) config = Config.__new__(Config) config._config = test_config_dict config.config_path = None # 添加属性以兼容接口 class MockConfig: def __init__(self, data): self._data = data def get(self, key, default=None): keys = key.split('.') value = self._data for k in keys: if isinstance(value, dict) and k in value: value = value[k] else: return default return value @property def vault_path(self): return Path(self._data['git']['vault_path']) return MockConfig(test_config_dict) def test_extract_only(): """测试仅提取功能""" print("\n" + "=" * 80) print("测试 1: 提取功能") print("=" * 80 + "\n") config = create_test_config() pipeline = MainPipeline(config=config, enable_git_sync=False) # 测试BV号 test_bv = "BV1MnFNz5EDL" # 可以替换为实际的测试视频BV号 print(f"测试视频: {test_bv}\n") try: # 提取 extractor_data = pipeline._extract_video(test_bv) print("\n✅ 提取测试通过!") print(f" 标题: {extractor_data.get('metadata', {}).get('title', 'N/A')}") print(f" 作者: {extractor_data.get('metadata', {}).get('author', 'N/A')}") print(f" 时长: {extractor_data.get('metadata', {}).get('duration', 'N/A')}") print(f" 字幕: {'有' if extractor_data.get('subtitle') else '无'}") return extractor_data except Exception as e: print(f"\n❌ 提取测试失败: {e}") import traceback traceback.print_exc() return None def test_full_pipeline(extractor_data=None): """测试完整流程""" print("\n" + "=" * 80) print("测试 2: 完整流程(提取 → 处理 → 输出)") print("=" * 80 + "\n") config = create_test_config() pipeline = MainPipeline(config=config, enable_git_sync=False) # 如果没有传入提取数据,先提取 if extractor_data is None: test_bv = "BV1MnFNz5EDL" print(f"测试视频: {test_bv}\n") try: extractor_data = pipeline._extract_video(test_bv) except Exception as e: print(f"❌ 提取失败,无法继续测试: {e}") return False try: # 完整流程 test_bv = extractor_data.get('metadata', {}).get('bvid', 'BV1MnFNz5EDL') result = pipeline.process_video(test_bv) if result['success']: print("\n" + "✅" * 40) print("完整流程测试通过!") print("✅" * 40 + "\n") # 显示结果 print(result['message']) # 检查生成的文件 if result['content'] and result['content'].output_path: output_file = Path(result['content'].output_path) if output_file.exists(): file_size = output_file.stat().st_size print(f"\n📄 输出文件:") print(f" 路径: {output_file}") print(f" 大小: {file_size:,} 字节") print(f" 存在: ✅") else: print(f"\n⚠️ 输出文件不存在: {output_file}") return True else: print(f"\n❌ 完整流程测试失败: {result.get('error', 'Unknown error')}") return False except Exception as e: print(f"\n❌ 完整流程测试异常: {e}") import traceback traceback.print_exc() return False def test_error_handling(): """测试错误处理""" print("\n" + "=" * 80) print("测试 3: 错误处理") print("=" * 80 + "\n") config = create_test_config() pipeline = MainPipeline(config=config, enable_git_sync=False) # 测试无效BV号 invalid_bv = "BVinvalid" print(f"测试无效BV号: {invalid_bv}\n") try: result = pipeline.process_video(invalid_bv) if not result['success']: print("✅ 错误处理测试通过!") print(f" 正确捕获了错误: {result.get('error', 'N/A')}") return True else: print("❌ 错误处理测试失败:应该失败但成功了") return False except Exception as e: print(f"⚠️ 测试异常: {e}") # 异常也可能是正确的(如果没有正确捕获) return True def cleanup_test_env(): """清理测试环境""" print("\n" + "=" * 80) print("清理测试环境") print("=" * 80 + "\n") config = create_test_config() temp_dir = config.get('temp_dir') if temp_dir and Path(temp_dir).exists(): print(f"删除测试目录: {temp_dir}") shutil.rmtree(temp_dir) print("✅ 清理完成") else: print("⚠️ 测试目录不存在或未配置") def main(): """运行所有测试""" print("\n" + "=" * 80) print("Obsidian KB - 主流程集成测试") print("=" * 80) print("\n测试说明:") print(" - 测试1: 提取功能") print(" - 测试2: 完整流程(提取 → 处理 → 输出)") print(" - 测试3: 错误处理") print(" - 使用测试配置,不执行Git同步") results = {} try: # 测试1: 提取 extractor_data = test_extract_only() results['extract'] = extractor_data is not None # 测试2: 完整流程 results['full_pipeline'] = test_full_pipeline(extractor_data) # 测试3: 错误处理 results['error_handling'] = test_error_handling() # 汇总结果 print("\n" + "=" * 80) print("测试结果汇总") print("=" * 80 + "\n") print(f" 测试1 - 提取功能: {'✅ 通过' if results['extract'] else '❌ 失败'}") print(f" 测试2 - 完整流程: {'✅ 通过' if results['full_pipeline'] else '❌ 失败'}") print(f" 测试3 - 错误处理: {'✅ 通过' if results['error_handling'] else '❌ 失败'}") all_passed = all(results.values()) print(f"\n 总体结果: {'✅ 全部通过' if all_passed else '❌ 有测试失败'}") except KeyboardInterrupt: print("\n\n⚠️ 测试被用户中断") except Exception as e: print(f"\n❌ 测试运行异常: {e}") import traceback traceback.print_exc() finally: # 清理测试环境 print("\n") cleanup_test_env() return 0 if all(results.values()) else 1 if __name__ == '__main__': sys.exit(main())