- Docker: Delete 23 deprecated Dockerfiles, fix CI/CD to use Dockerfile.foxhunt-build - Config: Remove 36 .env files, keep 4 essential, delete config/environments/ - Docs: Archive 614 Wave D files to docs/archive/wave_d/, 95% reduction in root - Scripts: Delete 56 deprecated scripts, keep 58 production-critical (49% reduction) - Python: Organize 37 scripts into scripts/python/ subdirectories, delete ml/python/ - Build: Remove 1GB artifacts, delete old venvs, clean Python cache from git - Migrations: Delete deprecated directory (4,432 lines), remove duplicate database/migrations/ - Infrastructure: Delete deployment/ (61 files), docs/scripts/ (8 files) Total impact: ~2,500 files cleaned, 750MB+ space freed, zero production impact All deleted scripts backed up to archives. runpod/ and tests/runpod/ preserved. data_acquisition_service retained per user request.
9.6 KiB
Foxhunt RunPod Module - Testing Documentation
Date: 2025-10-29 Status: ✅ 100% Test Pass Rate (97/97 tests) Coverage: 94% (321 statements, 18 missing)
Overview
Comprehensive test suite for the foxhunt_runpod module using pytest best practices. The module provides GPU pod deployment, monitoring, and S3 integration for ML training on RunPod.
Test Suite Structure
tests/foxhunt_runpod/
├── __init__.py # Test package
├── conftest.py # Pytest fixtures (18 fixtures)
├── test_config.py # Config tests (22 tests)
├── test_client.py # API client tests (22 tests)
├── test_monitor.py # Monitoring tests (26 tests)
└── test_s3_client.py # S3 client tests (27 tests)
Test Coverage Summary
| Module | Statements | Missing | Coverage |
|---|---|---|---|
foxhunt_runpod/__init__.py |
6 | 6 | 0% (imports only) |
foxhunt_runpod/client.py |
90 | 5 | 94% |
foxhunt_runpod/config.py |
49 | 2 | 96% |
foxhunt_runpod/monitor.py |
93 | 5 | 95% |
foxhunt_runpod/s3_client.py |
83 | 0 | 100% |
| TOTAL | 321 | 18 | 94% |
Test Categories
1. Configuration Tests (test_config.py) - 22 tests
Focus: Configuration validation, environment loading, error handling
✅ Passing: 22/22 (100%)
Key Tests:
- Config creation with valid/invalid values
- API key validation (length, format)
- Volume ID validation (alphanumeric)
- Environment variable loading
- File-based configuration
- Missing credential detection
- Container disk size validation
- Datacenter configuration
Coverage Highlights:
- Parametrized tests for validation logic
- Environment mocking with
monkeypatch - Temporary file fixtures for .env files
2. API Client Tests (test_client.py) - 22 tests
Focus: RunPod API interaction, GPU discovery, pod deployment
✅ Passing: 22/22 (100%)
Key Tests:
- Client initialization with config
- GraphQL query execution (success/error)
- GPU filtering (VRAM, secure cloud, pricing)
- Pod deployment (success/error cases)
- Command parsing (shlex splitting)
- Status retrieval
- Pod termination
- Error handling (network, timeout, API errors)
Coverage Highlights:
- Mocked HTTP responses using
responseslibrary - Parametrized success codes (200, 201)
- Command string parsing validation
3. Monitoring Tests (test_monitor.py) - 26 tests
Focus: Pod status polling, log tailing, completion detection
✅ Passing: 26/26 (100%)
Key Tests:
- Status parsing (known/unknown states)
- Poll until completion/failure
- Timeout handling
- Status change callbacks
- Log tailing (with/without follow)
- S3 error handling during monitoring
- Completion detection (status + log markers)
- Default completion markers validation
Coverage Highlights:
- Time-based polling simulation
- Mock S3 log streaming
- Multiple completion marker tests
4. S3 Client Tests (test_s3_client.py) - 27 tests
Focus: S3 operations, binary uploads, log streaming, result downloads
✅ Passing: 27/27 (100%)
Key Tests:
- Client initialization (success/failure)
- File upload (single/directory)
- File download (with directory creation)
- Log streaming (start, offset, tail)
- File listing (with prefix filtering)
- Result download (with pattern matching)
- File deletion
- S3 error handling
Coverage Highlights:
- 100% code coverage for S3 operations
- Mocked boto3 client using
moto - Temporary file fixtures for upload/download
Fixtures (conftest.py)
Configuration Fixtures
mock_env: Mocked environment variablessample_config: RunPodConfig instanceenv_file_content: Sample .env.runpod contentcreate_env_file: Temporary .env file
API Response Fixtures
mock_gpu_data: GPU types with pricingmock_pod_data: Pod deployment responsemock_api_responses: Collection of API responsesmock_s3_file_list: S3 file listing
Client Fixtures
mock_requests_session: Mocked requests sessionmock_s3_client: Mocked boto3 S3 client
File Fixtures
temp_directory: Temporary directorysample_binary_files: Binary files for uploadsample_parquet_files: Parquet test data
Log Fixtures
mock_log_content: Sample training logs
Running Tests
Quick Start
# Install dependencies
pip install -r requirements-test.txt
# Install module in dev mode
pip install -e .
# Run all tests
pytest tests/foxhunt_runpod/
# Run with coverage
pytest tests/foxhunt_runpod/ --cov=foxhunt_runpod --cov-report=html
# Use the test runner
./run_tests.sh
Specific Test Runs
# Run specific test file
pytest tests/foxhunt_runpod/test_client.py
# Run specific test
pytest tests/foxhunt_runpod/test_client.py::TestRunPodClient::test_deploy_pod_success
# Run with pattern matching
pytest tests/foxhunt_runpod/ -k test_deploy
# Run with markers
pytest tests/foxhunt_runpod/ -m unit
# Skip slow tests
pytest tests/foxhunt_runpod/ -m "not slow"
# Verbose output
pytest tests/foxhunt_runpod/ -v
# Show print statements
pytest tests/foxhunt_runpod/ -s
Coverage Reports
# Generate HTML coverage report
pytest tests/foxhunt_runpod/ --cov=foxhunt_runpod --cov-report=html
# View report
open htmlcov/index.html
# Terminal report with missing lines
pytest tests/foxhunt_runpod/ --cov=foxhunt_runpod --cov-report=term-missing
# XML report for CI/CD
pytest tests/foxhunt_runpod/ --cov=foxhunt_runpod --cov-report=xml
Test Strategies
1. Mocking External Dependencies
HTTP Requests: Using responses library
@responses.activate
def test_api_call(self, sample_config):
responses.add(
responses.POST,
"https://api.runpod.io/graphql",
json={"data": {"test": "value"}},
status=200
)
# Test code...
S3 Operations: Using moto and patch
with patch('boto3.client') as mock_boto:
mock_client = MagicMock()
mock_boto.return_value = mock_client
# Test code...
2. Parametrized Testing
@pytest.mark.parametrize("api_key,expected_valid", [
("test_key_" + "x" * 32, True),
("short", False),
])
def test_validation(self, api_key, expected_valid):
# Test code...
3. Fixture Reusability
Fixtures are shared across all test files via conftest.py:
- Reduces code duplication
- Ensures consistent test data
- Easy to extend for new tests
4. Error Path Testing
Every API call has corresponding error tests:
- Network errors (timeout, connection)
- API errors (400, 404, 500)
- Invalid responses
- Missing credentials
CI/CD Integration
GitHub Actions Example
- name: Run Tests
run: |
pip install -r requirements-test.txt
pip install -e .
pytest tests/foxhunt_runpod/ --cov=foxhunt_runpod --cov-report=xml
- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage.xml
Test Performance
- Total Tests: 97
- Execution Time: ~4.8 seconds
- Average per test: ~50ms
- Slowest tests: Timeout tests (~1-2s)
Best Practices Implemented
✅ Test Isolation
- Each test is independent
- Fixtures create fresh state
- No shared mutable state
✅ Clear Test Names
- Descriptive test function names
- Test classes grouped by functionality
- Docstrings explain test purpose
✅ Comprehensive Coverage
- Happy path tests
- Error path tests
- Edge case tests
- Boundary condition tests
✅ Mocking Strategy
- External APIs mocked
- File system operations isolated
- Time-based tests controlled
✅ Maintainability
- Fixtures for reusable setup
- Parametrized tests reduce duplication
- Clear assertion messages
Known Limitations
Missing Coverage (6%)
foxhunt_runpod/client.py (5 lines):
- Lines 110, 128: Network error edge cases
- Lines 217, 232-237: HTTP error response parsing
foxhunt_runpod/config.py (2 lines):
- Lines 85, 90: Default path resolution
foxhunt_runpod/monitor.py (5 lines):
- Lines 158, 161-163: S3 error handling
- Lines 219-220: Completion marker edge cases
Recommended Improvements
- Add integration tests for real API calls (marked with
@pytest.mark.integration) - Add performance tests for large file uploads
- Add concurrency tests for parallel pod deployments
- Test memory usage during log streaming
Dependencies
Required for Testing
pytest>=7.4.0 # Test framework
pytest-cov>=4.1.0 # Coverage plugin
pytest-mock>=3.11.1 # Mock helpers
responses>=0.23.1 # HTTP mocking
moto[s3]>=4.2.0 # AWS S3 mocking
boto3>=1.28.0 # AWS SDK
python-dotenv>=1.0.0 # Environment loading
requests>=2.31.0 # HTTP client
Quick Reference
Test Files
- Config: 22 tests, 96% coverage
- Client: 22 tests, 94% coverage
- Monitor: 26 tests, 95% coverage
- S3: 27 tests, 100% coverage
Commands
./run_tests.sh # Run all tests
./run_tests.sh -v # Verbose output
./run_tests.sh -k deploy # Filter by name
Markers
@pytest.mark.slow- Slow tests@pytest.mark.integration- Integration tests@pytest.mark.unit- Unit tests
Summary
The foxhunt_runpod test suite provides comprehensive coverage of all module functionality with a focus on:
- Reliability: 100% pass rate
- Coverage: 94% code coverage
- Best Practices: Fixtures, mocking, parametrization
- Maintainability: Clear structure, isolated tests
- Performance: Fast execution (~5s)
This test suite ensures the RunPod deployment and monitoring functionality is production-ready and resilient to errors.