Files
journal_organizer/test_application_startup.py
windyboy f7e54692a9 Initial project setup: Obsidian intelligent journal organizer
- Add core agent architecture with Command + Skill pattern
- Implement Claude API integration for content analysis
- Add Obsidian REST API integration for vault operations
- Create conversational interface (v2.0) with natural language processing
- Add comprehensive configuration management and validation
- Include project documentation and developer guides
- Set up testing framework with unit, integration, and property tests
- Add Kiro specs for Claude API configuration and code quality improvements
- Configure project steering files for development guidelines
2025-12-31 17:55:10 +08:00

282 lines
9.7 KiB
Python

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