# Integration Tests - Storm Logger

## Quick Overview for Gemini

Integration tests validate the interaction between Storm Logger components and external systems. These tests ensure that all parts work together correctly in realistic scenarios.

## Test Scope

```
integration/
├── test_full_integration.py  # Complete system integration tests
└── (future tests)            # Framework-specific integration tests
```

## Integration Test Philosophy

### What We Test
1. **Component Interactions**: How modules work together
2. **Framework Integration**: Django, Flask, FastAPI compatibility
3. **External Systems**: File systems, databases, cloud services
4. **End-to-End Workflows**: Complete logging scenarios
5. **Configuration Loading**: Environment and file-based configs

### What We Don't Mock
- File system operations
- Database connections (when testing DB handlers)
- Framework internals
- Time-based operations (unless necessary)

## Key Integration Scenarios

### 1. Full System Integration
```python
def test_complete_logging_workflow():
    """Test logger from initialization to output."""
    # 1. Configure logger
    config = StormLoggerConfig.from_env()
    
    # 2. Initialize with all components
    logger = ProfessionalStormLogger(config)
    
    # 3. Log with business metrics
    logger.track_business_event("test", {"value": 100})
    
    # 4. Verify all outputs
    assert log_file_exists()
    assert metrics_collected()
    assert console_output_formatted()
```

### 2. Django Integration
```python
def test_django_middleware_integration():
    """Test Django request/response logging."""
    # Setup Django test client
    client = Client()
    
    # Make request
    response = client.get('/api/test/')
    
    # Verify logs contain request info
    assert request_logged()
    assert response_time_tracked()
    assert user_context_captured()
```

### 3. Multi-Handler Setup
```python
def test_multiple_handlers_work_together():
    """Test console, file, and cloud handlers."""
    logger = setup_multi_handler_logger()
    
    logger.error("Critical error", exc_info=True)
    
    # Verify all handlers received the message
    assert console_shows_error()
    assert file_contains_traceback()
    assert cloud_service_notified()
```

## Testing Patterns

### 1. Real File Operations
```python
def test_rotating_file_handler(temp_log_dir):
    """Test actual file rotation."""
    config = StormLoggerConfig(
        log_dir=temp_log_dir,
        max_file_size="1MB",
        backup_count=3
    )
    logger = StormLogger(config)
    
    # Generate enough logs to trigger rotation
    for i in range(10000):
        logger.info(f"Message {i}" * 100)
    
    # Verify rotation occurred
    log_files = list(temp_log_dir.glob("*.log*"))
    assert len(log_files) == 4  # main + 3 backups
```

### 2. Database Handler Testing
```python
@pytest.mark.django_db
def test_database_logging(django_user):
    """Test Django database log handler."""
    logger = get_storm_logger("test")
    
    with logger.context(user=django_user):
        logger.warning("User action", action="delete")
    
    # Verify database record
    log_entry = LogEntry.objects.latest('timestamp')
    assert log_entry.user == django_user
    assert log_entry.level == "WARNING"
    assert log_entry.context["action"] == "delete"
```

### 3. Performance Under Load
```python
def test_high_volume_logging(benchmark):
    """Test system under heavy load."""
    logger = get_storm_logger("performance")
    
    def log_burst():
        for _ in range(1000):
            logger.info("High volume message")
    
    # Benchmark performance
    stats = benchmark(log_burst)
    
    # Verify no message loss
    assert count_logged_messages() == 1000
    assert stats['mean'] < 1.0  # < 1 second for 1000 messages
```

## Environment Setup

### Test Configuration
```python
@pytest.fixture
def integration_config():
    """Realistic configuration for integration tests."""
    return StormLoggerConfig(
        level="DEBUG",
        enable_color=True,
        enable_metrics=True,
        handlers={
            "console": {"class": "StormConsoleHandler"},
            "file": {"class": "RotatingFileHandler"},
            "database": {"class": "DatabaseHandler"}
        }
    )
```

### Django Test Settings
```python
# tests/integration/django_settings.py
STORM_LOGGER_CONFIG = {
    'version': 1,
    'handlers': {
        'storm_db': {
            'class': 'storm_logger.integrations.django.DatabaseLogHandler',
            'model': 'myapp.LogEntry'
        }
    }
}
```

## Common Integration Points

### 1. Configuration Loading
```python
def test_loads_from_multiple_sources():
    """Test configuration precedence."""
    # Set environment variables
    os.environ['STORM_LOGGER_LEVEL'] = 'ERROR'
    
    # Create config file
    config_file = Path("storm_config.yaml")
    config_file.write_text("level: WARNING")
    
    # Load with precedence
    config = StormLoggerConfig.load()
    
    # Env vars should override file
    assert config.level == "ERROR"
```

### 2. Context Propagation
```python
def test_context_across_threads():
    """Test context manager in threaded environment."""
    logger = get_storm_logger("threading")
    results = []
    
    def worker(user_id):
        with logger.context(user_id=user_id):
            logger.info("Worker task")
            results.append(logger.get_context())
    
    threads = [Thread(target=worker, args=(i,)) for i in range(5)]
    for t in threads:
        t.start()
    for t in threads:
        t.join()
    
    # Each thread should have its own context
    assert len(set(r['user_id'] for r in results)) == 5
```

### 3. Error Recovery
```python
def test_handles_handler_failures():
    """Test graceful degradation."""
    # Configure with failing handler
    config = StormLoggerConfig(
        handlers={
            "broken": {"class": "NonExistentHandler"},
            "console": {"class": "StormConsoleHandler"}
        }
    )
    
    logger = StormLogger(config)
    logger.error("Test message")
    
    # Should still log to console
    assert console_received_message()
    assert len(logger.handlers) == 1
```

## Testing External Services

### Mock vs Real Services
```python
@pytest.mark.integration
def test_real_aws_integration():
    """Test with actual AWS services."""
    if not os.environ.get('AWS_ACCESS_KEY_ID'):
        pytest.skip("AWS credentials not available")
    
    logger = setup_aws_logger()
    logger.info("CloudWatch test")
    
    # Verify in CloudWatch (with retry)
    assert wait_for_cloudwatch_log()

@pytest.mark.unit
def test_mocked_aws_integration():
    """Test with mocked AWS services."""
    with mock_aws():
        logger = setup_aws_logger()
        logger.info("Mocked CloudWatch test")
```

## Performance Integration Tests

### Throughput Testing
```python
def test_sustained_throughput():
    """Test sustained logging performance."""
    logger = get_storm_logger("throughput")
    duration = 60  # seconds
    start = time.time()
    count = 0
    
    while time.time() - start < duration:
        logger.info(f"Message {count}")
        count += 1
    
    throughput = count / duration
    assert throughput > 1000  # >1000 msgs/second
```

### Memory Usage
```python
def test_memory_stability():
    """Test for memory leaks."""
    import psutil
    process = psutil.Process()
    
    logger = get_storm_logger("memory")
    initial_memory = process.memory_info().rss
    
    # Log heavily
    for i in range(100000):
        logger.info(f"Memory test {i}")
    
    # Force garbage collection
    import gc
    gc.collect()
    
    final_memory = process.memory_info().rss
    memory_growth = final_memory - initial_memory
    
    # Should not grow more than 50MB
    assert memory_growth < 50 * 1024 * 1024
```

## Debugging Integration Tests

### 1. Enable Verbose Logging
```python
@pytest.fixture
def debug_integration():
    """Enable debug output for integration tests."""
    import logging
    logging.basicConfig(level=logging.DEBUG)
    
    # Also enable Storm Logger debug
    os.environ['STORM_DEBUG'] = '1'
```

### 2. Capture All Outputs
```python
def test_with_full_capture(capsys, caplog, tmp_path):
    """Capture console, logs, and files."""
    logger = setup_test_logger(tmp_path)
    logger.error("Test error")
    
    # Check all outputs
    console = capsys.readouterr()
    logs = caplog.records
    files = list(tmp_path.glob("*.log"))
    
    print(f"Console: {console}")
    print(f"Logs: {logs}")
    print(f"Files: {files}")
```

## Running Integration Tests

```bash
# Run all integration tests
pytest tests/integration/ -v

# Run with real external services
pytest tests/integration/ -m integration

# Run specific integration
pytest tests/integration/test_full_integration.py::test_django_integration

# With coverage
pytest tests/integration/ --cov=storm_logger --cov-report=html
```

## Best Practices

### 1. Test Isolation
- Use separate test databases
- Clean up file system artifacts
- Reset global state between tests

### 2. Realistic Scenarios
- Use production-like configurations
- Test with actual data volumes
- Simulate real error conditions

### 3. Performance Awareness
- Set reasonable timeouts
- Test with realistic load
- Monitor resource usage

## Next Steps

- Add framework-specific integration tests
- Test cloud service integrations
- Implement stress testing scenarios
- Add multi-process testing