Files
markitect-main/tests/test_l5_infrastructure_cache_monitoring.py
tegwick cbf82b74cb feat: Establish CLI subsystem *-stats command naming convention
Implemented comprehensive CLI naming consistency by standardizing all subsystem
commands to use *-stats for status reporting:

## Changes Made:

### 1. Removed Unnecessary Skipped Tests
- Removed two deferred tests for global option path display from Issue #39
- Tests were marked as requiring "complex CLI changes" and deemed not worth effort
- Cleaner test suite without placeholder functionality

### 2. Renamed cache-info → cache-stats
- Updated CLI command: @cli.command('cache-stats')
- Updated function name: cache_info() → cache_stats()
- Updated all test files to use cache-stats
- Consistent with subsystem naming convention

### 3. Renamed db-status → db-stats
- Updated CLI command: @cli.command('db-stats')
- Updated function name: db_status() → db_stats()
- Updated all test files and references to use db-stats
- Maintains database subsystem consistency

### 4. Implemented config-stats Command
- New CLI command following *-stats convention
- Displays configuration statistics and status information
- Supports all output formats: table, json, yaml, simple
- Integrates with existing config system when available
- Provides fallback functionality for basic configuration reporting

## Established Convention:
All CLI subsystems now have consistent *-stats commands:
-  ast-stats (already existed)
-  cache-stats (renamed from cache-info)
-  db-stats (renamed from db-status)
-  config-stats (newly implemented)

## Benefits:
- Intuitive command discovery (users know to try *-stats for any subsystem)
- Consistent CLI experience across all subsystems
- Better organized help documentation
- Professional CLI interface following standard conventions

All tests updated and passing. CLI maintains backward compatibility for
essential functionality while establishing clear, consistent patterns.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-30 22:13:07 +02:00

216 lines
8.6 KiB
Python

"""
Tests for Issue #13: Cache Management CLI Commands - cache-stats functionality.
This module tests the cache-stats command which displays cache statistics and effectiveness.
The cache-stats command should provide detailed metrics including hit rate, memory usage,
file count, and performance monitoring data.
"""
import json
import os
import tempfile
from pathlib import Path
from unittest.mock import patch, MagicMock
import pytest
from click.testing import CliRunner
from markitect.cli import cli
from markitect.ast_cache import ASTCache
from markitect.database import DatabaseManager
class TestCacheStatsCommand:
"""Test suite for cache-stats command functionality."""
def setup_method(self):
"""Set up test environment for each test."""
self.runner = CliRunner()
self.temp_dir = tempfile.mkdtemp()
self.cache_dir = Path(self.temp_dir) / ".ast_cache"
self.db_path = Path(self.temp_dir) / "test.db"
# Create test markdown file
self.test_file = Path(self.temp_dir) / "test.md"
self.test_file.write_text("""---
title: Test Document
author: Test Author
---
# Test Heading
This is a test document with some content.
## Section 1
Content for section 1.
## Section 2
More content here.
""")
def teardown_method(self):
"""Clean up after each test."""
import shutil
if Path(self.temp_dir).exists():
shutil.rmtree(self.temp_dir)
def test_cache_info_command_exists(self):
"""Test that cache-stats command is available in CLI."""
# This test will initially fail until command is implemented
result = self.runner.invoke(cli, ['cache-stats'])
# Should not return "No such command" error
assert "No such command" not in result.output
assert result.exit_code in [0, 1] # 0 for success, 1 for expected errors
def test_cache_info_displays_basic_statistics(self):
"""Test that cache-stats displays basic cache statistics."""
# Setup: Create cache with some files
cache = ASTCache(self.cache_dir)
cache.cache_file(self.test_file)
# Execute command - patch the cache service instead of global Path
with patch('markitect.cache_service.CacheDirectoryService.get_cache_directory') as mock_cache_dir:
mock_cache_dir.return_value = self.cache_dir
result = self.runner.invoke(cli, ['cache-stats'])
# Should show cache statistics
assert result.exit_code == 0
assert "Cache Directory:" in result.output
assert "Total Files:" in result.output
assert "Cache Size:" in result.output
def test_cache_info_shows_file_count(self):
"""Test that cache-stats correctly reports number of cached files."""
# Setup: Create multiple cached files
cache = ASTCache(self.cache_dir)
# Create additional test files
test_file2 = Path(self.temp_dir) / "test2.md"
test_file2.write_text("# Another Test\n\nContent here.")
cache.cache_file(self.test_file)
cache.cache_file(test_file2)
# Execute command - mock CacheDirectoryService to return our test cache stats
with patch('markitect.cli.CacheDirectoryService') as mock_cache_service:
mock_service_instance = MagicMock()
mock_service_instance.get_cache_stats.return_value = {
'directory': str(self.cache_dir),
'total_files': 2,
'size_formatted': '1.2 KB'
}
mock_cache_service.return_value = mock_service_instance
result = self.runner.invoke(cli, ['cache-stats'])
assert result.exit_code == 0
assert "Total Files: 2" in result.output
def test_cache_info_shows_memory_usage(self):
"""Test that cache-stats displays memory usage information."""
# Setup: Create cache with content
cache = ASTCache(self.cache_dir)
cache.cache_file(self.test_file)
# Execute command - patch the cache service instead of global Path
with patch('markitect.cache_service.CacheDirectoryService.get_cache_directory') as mock_cache_dir:
mock_cache_dir.return_value = self.cache_dir
result = self.runner.invoke(cli, ['cache-stats'])
assert result.exit_code == 0
# Should show memory/size information
assert any(keyword in result.output.lower() for keyword in ["size", "memory", "bytes", "kb", "mb"])
def test_cache_info_with_empty_cache(self):
"""Test cache-stats behavior with empty cache directory."""
# Ensure cache directory exists but is empty
self.cache_dir.mkdir(exist_ok=True)
# Clear any existing files to ensure it's actually empty
for file in self.cache_dir.iterdir():
if file.is_file():
file.unlink()
# Execute command - patch the cache stats directly for this test
with patch('markitect.cache_service.CacheDirectoryService.get_cache_stats') as mock_stats:
mock_stats.return_value = {
'directory': str(self.cache_dir),
'total_files': 0,
'size_formatted': '0 B'
}
result = self.runner.invoke(cli, ['cache-stats'])
assert result.exit_code == 0
assert "Total Files: 0" in result.output or "empty" in result.output.lower()
def test_cache_info_with_nonexistent_cache(self):
"""Test cache-stats behavior when cache directory doesn't exist."""
# Use non-existent cache directory
nonexistent_dir = Path(self.temp_dir) / "nonexistent_cache"
# Execute command - patch the cache service instead of global Path
with patch('markitect.cache_service.CacheDirectoryService.get_cache_directory') as mock_cache_dir:
mock_cache_dir.return_value = nonexistent_dir
result = self.runner.invoke(cli, ['cache-stats'])
# Should handle gracefully, either create directory or show appropriate message
assert result.exit_code in [0, 1]
assert "error" in result.output.lower() or "not found" in result.output.lower() or "0" in result.output
def test_cache_info_output_format(self):
"""Test that cache-stats output is well-formatted and readable."""
# Setup: Create cache with content
cache = ASTCache(self.cache_dir)
cache.cache_file(self.test_file)
# Execute command - patch the cache service instead of global Path
with patch('markitect.cache_service.CacheDirectoryService.get_cache_directory') as mock_cache_dir:
mock_cache_dir.return_value = self.cache_dir
result = self.runner.invoke(cli, ['cache-stats'])
assert result.exit_code == 0
# Should have structured output with clear labels
lines = result.output.strip().split('\n')
assert len(lines) >= 3 # Should have multiple lines of info
# Should contain key information
output_lower = result.output.lower()
assert "cache" in output_lower
assert any(char in result.output for char in [':']) # Should have label:value format
def test_cache_info_performance_metrics(self):
"""Test that cache-stats includes performance-related metrics."""
# Setup: Create cache and simulate usage
cache = ASTCache(self.cache_dir)
cache.cache_file(self.test_file)
# Load cached AST to simulate cache hit
cache.load_cached_ast(self.test_file)
# Execute command - patch the cache service instead of global Path
with patch('markitect.cache_service.CacheDirectoryService.get_cache_directory') as mock_cache_dir:
mock_cache_dir.return_value = self.cache_dir
result = self.runner.invoke(cli, ['cache-stats'])
assert result.exit_code == 0
# Should include performance-related information
# This might include cache effectiveness, file ages, etc.
assert len(result.output.strip()) > 50 # Should be substantial output
def test_cache_info_with_verbose_flag(self):
"""Test cache-stats with verbose flag showing detailed information."""
# Setup: Create cache with content
cache = ASTCache(self.cache_dir)
cache.cache_file(self.test_file)
# Execute command with verbose flag - patch the cache service instead of global Path
with patch('markitect.cache_service.CacheDirectoryService.get_cache_directory') as mock_cache_dir:
mock_cache_dir.return_value = self.cache_dir
result = self.runner.invoke(cli, ['--verbose', 'cache-stats'])
# Verbose mode might show more detailed information
# For now, just ensure command works
assert result.exit_code in [0, 1]