# Unit Tests - Storm Logger

## Quick Overview for Gemini

This directory contains comprehensive unit tests for all Storm Logger components. Each test file focuses on a specific module or class, ensuring isolated testing with mocked dependencies.

## Test Organization

```
unit/
├── test_basic.py                    # Basic functionality tests
├── test_config.py                   # Configuration system tests
├── test_console.py                  # Console output tests
├── test_core_logger.py              # Core logger implementation
├── test_professional_logger.py      # Professional logger features
├── test_django_config.py            # Django configuration
├── test_interfaces.py               # Interface compliance
├── test_interfaces_comprehensive.py # Extended interface tests
├── test_message_formatter.py        # Message formatting
├── test_message_formatter_comprehensive.py # Advanced formatting
├── test_business_metrics.py         # Business metrics tracking
├── test_business_metrics_advanced.py # Advanced metrics features
├── test_sanitizer.py                # Log sanitization
└── test_sanitizer_advanced.py       # Advanced sanitization
```

## Testing Patterns

### 1. Test Structure
```python
class TestComponent:
    """Test suite for specific component."""
    
    def test_basic_functionality(self, fixture):
        """Test basic use case."""
        
    def test_edge_cases(self):
        """Test boundary conditions."""
        
    def test_error_handling(self):
        """Test exception scenarios."""
```

### 2. Common Fixtures (from conftest.py)
- `storm_logger`: Configured logger instance
- `basic_config`: Basic configuration
- `temp_log_dir`: Temporary directory for logs
- `mock_datetime`: Time mocking for consistent tests
- `capture_logs`: Log capture utility

### 3. Mocking Strategy
```python
@patch('storm_logger.core.logger.datetime')
def test_with_mock(self, mock_datetime):
    mock_datetime.now.return_value = datetime(2024, 1, 1)
    # Test with controlled time
```

## Key Test Categories

### Configuration Tests (`test_config.py`)
- Environment variable parsing
- Configuration validation
- Runtime reconfiguration
- Default values
- Type safety

### Core Logger Tests (`test_core_logger.py`)
- Basic logging levels
- Message formatting
- Handler management
- Context propagation
- Performance tracking

### Business Metrics Tests (`test_business_metrics*.py`)
- Event tracking
- Metric aggregation
- Performance measurement
- Report generation
- Data export

### Sanitization Tests (`test_sanitizer*.py`)
- PII detection
- Pattern matching
- Compliance modes
- Custom patterns
- Performance impact

### Interface Tests (`test_interfaces*.py`)
- ABC compliance
- Method signatures
- Type hints
- Contract validation

## Testing Best Practices

### 1. Isolation
```python
def test_isolated_component(self):
    # Use mocks for all dependencies
    with patch('external.dependency'):
        result = component.method()
    assert result == expected
```

### 2. Parametrized Testing
```python
@pytest.mark.parametrize("level,expected", [
    ("DEBUG", logging.DEBUG),
    ("INFO", logging.INFO),
    ("WARNING", logging.WARNING),
])
def test_log_levels(self, level, expected):
    # Test multiple scenarios efficiently
```

### 3. Error Scenarios
```python
def test_handles_invalid_input(self):
    with pytest.raises(ValueError, match="Invalid format"):
        logger.configure(format="invalid")
```

## Coverage Requirements

- **Target**: 95% for core modules
- **Minimum**: 90% overall
- **Critical Paths**: 100% required

### Running Coverage
```bash
pytest tests/unit/ --cov=storm_logger --cov-report=html
```

## Performance Considerations

### Benchmarking in Tests
```python
def test_performance_requirement(self, benchmark):
    result = benchmark(logger.info, "test message")
    assert benchmark.stats['mean'] < 0.001  # < 1ms
```

### Memory Testing
```python
def test_no_memory_leak(self):
    import tracemalloc
    tracemalloc.start()
    # Run operations
    snapshot = tracemalloc.take_snapshot()
    # Verify memory usage
```

## Common Test Patterns

### 1. Logger Configuration
```python
def test_custom_config(self, temp_log_dir):
    config = StormLoggerConfig(
        log_dir=temp_log_dir,
        level="DEBUG"
    )
    logger = StormLogger(config)
    assert logger.level == logging.DEBUG
```

### 2. Business Event Tracking
```python
def test_tracks_business_event(self, storm_logger):
    storm_logger.track_business_event(
        "user_signup",
        {"plan": "premium", "value": 99.99}
    )
    metrics = storm_logger.get_metrics_summary()
    assert metrics["events"]["user_signup"]["count"] == 1
```

### 3. Sanitization Testing
```python
def test_sanitizes_pii(self, sanitizer):
    message = "User SSN: 123-45-6789"
    sanitized = sanitizer.sanitize(message)
    assert "123-45-6789" not in sanitized
    assert "[REDACTED]" in sanitized
```

## Debugging Failed Tests

### 1. Enable Debug Output
```python
def test_with_debug(self, caplog):
    with caplog.at_level(logging.DEBUG):
        # Run test
        pass
    print(caplog.text)  # See all logs
```

### 2. Check Test Isolation
```python
@pytest.mark.order(1)  # Run first
def test_order_dependent(self):
    # Ensure test order doesn't affect results
```

### 3. Fixture Debugging
```python
def test_fixture_state(self, storm_logger):
    print(f"Logger config: {storm_logger.config}")
    print(f"Handlers: {storm_logger.handlers}")
```

## Quick Test Commands

```bash
# Run all unit tests
pytest tests/unit/

# Run specific test file
pytest tests/unit/test_core_logger.py

# Run specific test
pytest tests/unit/test_core_logger.py::TestStormLogger::test_basic_logging

# Run with verbose output
pytest tests/unit/ -v

# Run failed tests only
pytest tests/unit/ --lf

# Run tests matching pattern
pytest tests/unit/ -k "sanitiz"
```

## Adding New Tests

### 1. Create Test File
```python
# tests/unit/test_new_feature.py
import pytest
from storm_logger.new_feature import NewFeature

class TestNewFeature:
    """Test suite for NewFeature."""
    
    @pytest.fixture
    def feature(self):
        return NewFeature()
    
    def test_basic_functionality(self, feature):
        result = feature.process("input")
        assert result == "expected"
```

### 2. Use Existing Fixtures
```python
def test_with_logger(self, storm_logger):
    # Leverage common fixtures
    storm_logger.info("test")
```

### 3. Follow Naming Conventions
- Test files: `test_*.py`
- Test classes: `TestClassName`
- Test methods: `test_descriptive_name`

## Integration with CI/CD

Tests run automatically on:
- Pull requests
- Main branch commits
- Release tags

### GitLab CI Configuration
```yaml
test:unit:
  script:
    - pytest tests/unit/ --cov=storm_logger
  coverage: '/TOTAL.*\s+(\d+%)$/'
```

## Next Steps

- Review specific test files for examples
- Check `conftest.py` for available fixtures
- Run tests locally before committing
- Aim for high coverage on new features