This commit represents a comprehensive refactoring and enhancement of Baktainer: ## Core Architecture Improvements - Implemented comprehensive dependency injection system with DependencyContainer - Fixed critical singleton instantiation bug that was returning Procs instead of service instances - Replaced problematic Concurrent::FixedThreadPool with custom SimpleThreadPool implementation - Achieved 100% test pass rate (121 examples, 0 failures) after fixing 30+ failing tests ## New Features Implemented ### 1. Backup Rotation & Cleanup (BackupRotation) - Configurable retention policies by age, count, and disk space - Automatic cleanup with comprehensive statistics tracking - Empty directory cleanup and space monitoring ### 2. Backup Encryption (BackupEncryption) - AES-256-CBC and AES-256-GCM encryption support - Key derivation from passphrases or direct key input - Encrypted backup metadata storage ### 3. Operational Monitoring Suite - **Health Check Server**: HTTP endpoints for monitoring (/health, /status, /metrics) - **Web Dashboard**: Real-time monitoring dashboard with auto-refresh - **Prometheus Metrics**: Integration with monitoring systems - **Backup Monitor**: Comprehensive metrics tracking and performance alerts ### 4. Advanced Label Validation (LabelValidator) - Schema-based validation for all 12+ Docker labels - Engine-specific validation rules - Helpful error messages and warnings - Example generation for each database engine ### 5. Multi-Channel Notifications (NotificationSystem) - Support for Slack, Discord, Teams, webhooks, and log notifications - Event-based notifications for backups, failures, warnings, and health issues - Configurable notification thresholds ## Code Organization Improvements - Extracted responsibilities into focused classes: - ContainerValidator: Container validation logic - BackupOrchestrator: Backup workflow orchestration - FileSystemOperations: File I/O with comprehensive error handling - Configuration: Centralized environment variable management - BackupStrategy/Factory: Strategy pattern for database engines ## Testing Infrastructure - Added comprehensive unit and integration tests - Fixed timing-dependent test failures - Added RSpec coverage reporting (94.94% coverage) - Created test factories and fixtures ## Breaking Changes - Container class constructor now requires dependency injection - BackupCommand methods now use keyword arguments - Thread pool implementation changed from Concurrent to SimpleThreadPool ## Configuration New environment variables: - BT_HEALTH_SERVER_ENABLED: Enable health check server - BT_HEALTH_PORT/BT_HEALTH_BIND: Health server configuration - BT_NOTIFICATION_CHANNELS: Comma-separated notification channels - BT_ENCRYPTION_ENABLED/BT_ENCRYPTION_KEY: Backup encryption - BT_RETENTION_DAYS/COUNT: Backup retention policies This refactoring improves maintainability, testability, and adds enterprise-grade monitoring and operational features while maintaining backward compatibility for basic usage. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> |
||
---|---|---|
.. | ||
fixtures | ||
integration | ||
support | ||
unit | ||
examples.txt | ||
README.md | ||
spec_helper.rb |
Baktainer Testing Guide
This directory contains the complete test suite for Baktainer, including unit tests, integration tests, and testing infrastructure.
Test Structure
spec/
├── unit/ # Unit tests for individual components
│ ├── backup_command_spec.rb # Tests for backup command generation
│ ├── container_spec.rb # Tests for container management
│ └── baktainer_spec.rb # Tests for main runner class
├── integration/ # Integration tests with real containers
│ └── backup_workflow_spec.rb # End-to-end backup workflow tests
├── fixtures/ # Test data and configuration
│ ├── docker-compose.test.yml # Test database containers
│ └── factories.rb # Test data factories
├── support/ # Test support files
│ └── coverage.rb # Coverage configuration
├── spec_helper.rb # Main test configuration
└── README.md # This file
Running Tests
Quick Start
# Run unit tests only (fast)
cd app && bundle exec rspec spec/unit/
# Run all tests with coverage
cd app && COVERAGE=true bundle exec rspec
# Use the test runner script
cd app && bin/test --all --coverage
Test Runner Script
The bin/test
script provides a convenient way to run tests with various options:
# Run unit tests (default)
bin/test
# Run integration tests with container setup
bin/test --integration --setup --cleanup
# Run all tests with coverage
bin/test --all --coverage
# Show help
bin/test --help
Using Rake Tasks
# Install dependencies
rake install
# Run unit tests
rake spec
# Run integration tests
rake integration
# Run all tests
rake spec_all
# Run tests with coverage
rake coverage
# Full test suite with setup/cleanup
rake test_full
# Open coverage report
rake coverage_report
Test Categories
Unit Tests
Unit tests focus on individual components in isolation:
- Backup Command Tests (
backup_command_spec.rb
): Test command generation for different database engines - Container Tests (
container_spec.rb
): Test container discovery, validation, and backup orchestration - Runner Tests (
baktainer_spec.rb
): Test the main application runner, thread pool, and scheduling
Unit tests use mocks and stubs to isolate functionality and run quickly without external dependencies.
Integration Tests
Integration tests validate the complete backup workflow with real Docker containers:
- Container Discovery: Test finding containers with backup labels
- Database Backups: Test actual backup creation for PostgreSQL, MySQL, and SQLite
- Error Handling: Test graceful handling of failures and edge cases
- Concurrent Execution: Test thread pool and concurrent backup execution
Integration tests require Docker and may take longer to run.
Test Environment Setup
Dependencies
Install test dependencies:
cd app
bundle install
Required gems for testing:
rspec
- Testing frameworksimplecov
- Code coverage reportingfactory_bot
- Test data factorieswebmock
- HTTP request stubbing
Test Database Containers
Integration tests use Docker containers defined in spec/fixtures/docker-compose.test.yml
:
- PostgreSQL container with test database
- MySQL container with test database
- SQLite container with test database file
- Control container without backup labels
Start test containers:
cd app
docker-compose -f spec/fixtures/docker-compose.test.yml up -d
Stop test containers:
cd app
docker-compose -f spec/fixtures/docker-compose.test.yml down -v
Test Configuration
RSpec Configuration (.rspec
)
--require spec_helper
--format documentation
--color
--profile 10
--order random
Coverage Configuration
Test coverage is configured in spec/support/coverage.rb
:
- Minimum coverage: 80%
- Minimum per-file coverage: 70%
- HTML and console output formats
- Branch coverage tracking (Ruby 2.5+)
- Coverage tracking over time
Enable coverage:
COVERAGE=true bundle exec rspec
Environment Variables
Tests clean up environment variables between runs and use temporary directories for backup files.
Writing Tests
Unit Test Example
RSpec.describe Baktainer::BackupCommand do
describe '.postgres' do
it 'generates correct pg_dump command' do
result = described_class.postgres(login: 'user', password: 'pass', database: 'testdb')
expect(result).to be_a(Hash)
expect(result[:env]).to eq(['PGPASSWORD=pass'])
expect(result[:cmd]).to eq(['pg_dump', '-U', 'user', '-d', 'testdb'])
end
end
end
Integration Test Example
RSpec.describe 'PostgreSQL Backup', :integration do
let(:postgres_container) do
containers = Baktainer::Containers.find_all
containers.find { |c| c.engine == 'postgres' }
end
it 'creates a valid PostgreSQL backup' do
postgres_container.backup
backup_files = Dir.glob(File.join(test_backup_dir, '**', '*.sql'))
expect(backup_files).not_to be_empty
backup_content = File.read(backup_files.first)
expect(backup_content).to include('PostgreSQL database dump')
end
end
Test Helpers
Use test helpers defined in spec_helper.rb
:
# Create mock Docker container
container = mock_docker_container(labels)
# Create temporary backup directory
test_dir = create_test_backup_dir
# Set environment variables for test
with_env('BT_BACKUP_DIR' => test_dir) do
# test code
end
Continuous Integration
GitHub Actions
Add to .github/workflows/test.yml
:
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.3
bundler-cache: true
- name: Run tests
run: |
cd app
COVERAGE=true bundle exec rspec
- name: Upload coverage
uses: codecov/codecov-action@v3
Coverage Reporting
Coverage reports are generated in coverage/
directory:
coverage/index.html
- HTML reportcoverage/coverage.json
- JSON data- Console summary during test runs
Troubleshooting
Common Issues
- Docker containers not starting: Check Docker daemon is running and ports are available
- Permission errors: Ensure test script is executable (
chmod +x bin/test
) - Bundle errors: Run
bundle install
in theapp
directory - Coverage not working: Set
COVERAGE=true
environment variable
Debugging Tests
# Run specific test file
bundle exec rspec spec/unit/container_spec.rb
# Run specific test
bundle exec rspec spec/unit/container_spec.rb:45
# Run with debug output
bundle exec rspec --format documentation --backtrace
# Run integration tests with container logs
docker-compose -f spec/fixtures/docker-compose.test.yml logs
Performance
- Unit tests should complete in under 10 seconds
- Integration tests may take 30-60 seconds including container startup
- Use
bin/test --unit
for quick feedback during development - Run full test suite before committing changes
Best Practices
- Isolation: Each test should be independent and clean up after itself
- Descriptive Names: Use clear, descriptive test names and descriptions
- Mock External Dependencies: Use mocks for Docker API calls in unit tests
- Test Error Conditions: Include tests for error handling and edge cases
- Coverage: Aim for high test coverage, especially for critical backup logic
- Fast Feedback: Keep unit tests fast for quick development feedback