#!/usr/bin/env python3 """ Simple application startup validation test. Tests the application by running it as a module to validate basic functionality. """ import asyncio import json import logging import os import subprocess import sys import tempfile from pathlib import Path from typing import Dict, Any, List, Tuple # Configure logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" ) logger = logging.getLogger("ApplicationStartup") class ApplicationStartupTest: """Test application startup and basic functionality""" def __init__(self): self.test_results: List[Tuple[str, bool, str]] = [] self.temp_config_path: Path = None def create_test_config(self) -> Path: """Create a temporary test configuration file""" config_content = { 'obsidian': { 'vault_path': '/tmp/test_vault', 'rest_api': { 'url': 'https://localhost:27123', 'api_key': 'test-api-key', 'verify_ssl': False } }, 'claude': { 'api_key': 'test-api-key-placeholder', 'model': 'claude-3-5-sonnet-20241022', 'max_tokens': 4096, 'temperature': 0.7 }, 'journal': { 'daily_notes_folder': 'Daily', 'date_format': 'YYYY-MM-DD', 'file_extension': '.md' }, 'output': { 'experiences_folder': 'Knowledge/Experiences', 'lessons_folder': 'Knowledge/Lessons', 'tasks_folder': 'Tasks/Daily', 'problems_folder': 'Knowledge/Problems', 'achievements_folder': 'Knowledge/Achievements', 'improvements_folder': 'Knowledge/Improvements' }, 'logging': { 'level': 'INFO', 'file': 'logs/journal_organizer.log' } } # Create temporary config file temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) json.dump(config_content, temp_file, indent=2) temp_file.close() self.temp_config_path = Path(temp_file.name) return self.temp_config_path def cleanup(self): """Clean up temporary files""" if self.temp_config_path and self.temp_config_path.exists(): self.temp_config_path.unlink() def run_command(self, cmd: List[str], timeout: int = 30) -> Tuple[bool, str, str]: """Run a command and return success, stdout, stderr""" try: result = subprocess.run( cmd, capture_output=True, text=True, timeout=timeout, cwd=Path.cwd() ) return result.returncode == 0, result.stdout, result.stderr except subprocess.TimeoutExpired: return False, "", "Command timed out" except Exception as e: return False, "", str(e) def test_module_import(self) -> Tuple[str, bool, str]: """Test if the module can be imported""" test_name = "Module Import Test" cmd = [sys.executable, "-c", "import sys; sys.path.insert(0, '.'); import main; print('SUCCESS: Module imported')"] success, stdout, stderr = self.run_command(cmd, timeout=10) if success and "SUCCESS" in stdout: return test_name, True, "Module imported successfully" else: return test_name, False, f"Import failed: {stderr}" def test_help_command(self) -> Tuple[str, bool, str]: """Test the help command""" test_name = "Help Command Test" cmd = [sys.executable, "-m", "__main__", "--help"] success, stdout, stderr = self.run_command(cmd, timeout=10) if success and ("usage:" in stdout.lower() or "help" in stdout.lower()): return test_name, True, "Help command works" else: return test_name, False, f"Help command failed: {stderr}" def test_list_command(self) -> Tuple[str, bool, str]: """Test the list command""" test_name = "List Command Test" config_path = self.create_test_config() cmd = [sys.executable, "-m", "__main__", "--config", str(config_path), "list"] success, stdout, stderr = self.run_command(cmd, timeout=15) if success and ("organize" in stdout.lower() or "可用命令" in stdout): return test_name, True, "List command works" else: return test_name, False, f"List command failed: {stderr}" def test_check_deps_command(self) -> Tuple[str, bool, str]: """Test the check-deps command""" test_name = "Check Dependencies Command Test" cmd = [sys.executable, "-m", "__main__", "check-deps"] success, stdout, stderr = self.run_command(cmd, timeout=15) # This command should run regardless of missing dependencies if "检查依赖项状态" in stdout or "dependency" in stdout.lower() or success: return test_name, True, "Check-deps command works" else: return test_name, False, f"Check-deps command failed: {stderr}" def test_info_command(self) -> Tuple[str, bool, str]: """Test the info command""" test_name = "Info Command Test" config_path = self.create_test_config() cmd = [sys.executable, "-m", "__main__", "--config", str(config_path), "info"] success, stdout, stderr = self.run_command(cmd, timeout=15) if success and ("{" in stdout or "info" in stdout.lower()): return test_name, True, "Info command works" else: return test_name, False, f"Info command failed: {stderr}" def test_chat_help(self) -> Tuple[str, bool, str]: """Test the chat interface help""" test_name = "Chat Interface Help Test" cmd = [sys.executable, "-c", "import sys; sys.path.insert(0, '.'); import chat_main; print('SUCCESS: Chat module imported')"] success, stdout, stderr = self.run_command(cmd, timeout=10) if success and "SUCCESS" in stdout: return test_name, True, "Chat module can be imported" else: return test_name, False, f"Chat module import failed: {stderr}" def test_configuration_validation(self) -> Tuple[str, bool, str]: """Test configuration validation""" test_name = "Configuration Validation Test" # Test with valid config config_path = self.create_test_config() cmd = [sys.executable, "-c", f""" import sys sys.path.insert(0, '.') import json from pathlib import Path # Test config loading config_path = Path('{config_path}') with config_path.open('r') as f: config = json.load(f) print(f'SUCCESS: Config loaded with {{len(config)}} sections') """] success, stdout, stderr = self.run_command(cmd, timeout=10) if success and "SUCCESS" in stdout: return test_name, True, "Configuration validation works" else: return test_name, False, f"Configuration validation failed: {stderr}" def run_all_tests(self) -> List[Tuple[str, bool, str]]: """Run all startup tests""" logger.info("🚀 Starting application startup tests...") test_methods = [ self.test_module_import, self.test_help_command, self.test_list_command, self.test_check_deps_command, self.test_info_command, self.test_chat_help, self.test_configuration_validation ] for test_method in test_methods: try: logger.info(f"Running {test_method.__name__}...") result = test_method() self.test_results.append(result) status = "✅ PASS" if result[1] else "❌ FAIL" logger.info(f"{status} {result[0]}: {result[2]}") except Exception as e: error_result = (test_method.__name__, False, f"Test execution failed: {str(e)}") self.test_results.append(error_result) logger.error(f"❌ FAIL {error_result[0]}: {error_result[2]}") return self.test_results def generate_report(self) -> str: """Generate test report""" total_tests = len(self.test_results) passed_tests = sum(1 for _, success, _ in self.test_results if success) failed_tests = total_tests - passed_tests report = f""" {'='*60} APPLICATION STARTUP TEST REPORT {'='*60} Summary: Total Tests: {total_tests} Passed: {passed_tests} Failed: {failed_tests} Success Rate: {(passed_tests/total_tests*100):.1f}% Test Results: """ for test_name, success, message in self.test_results: status = "✅ PASS" if success else "❌ FAIL" report += f"\n{status} {test_name}: {message}" report += f"\n\n{'='*60}\n" return report def main(): """Main test function""" tester = ApplicationStartupTest() try: results = tester.run_all_tests() report = tester.generate_report() print(report) # Return appropriate exit code failed_count = sum(1 for _, success, _ in results if not success) return 0 if failed_count == 0 else 1 except Exception as e: logger.error(f"Test execution failed: {str(e)}") return 1 finally: tester.cleanup() if __name__ == "__main__": exit_code = main() sys.exit(exit_code)