This document outlines the testing standards and practices for the VideoAnnotator project.
The VideoAnnotator project uses pytest as its primary testing framework. All tests should be written using pytest conventions and features.
tests/
├── conftest.py # Pytest configuration and fixtures
├── test_all_pipelines.py # Test runner and organization
├── test_face_pipeline.py # Face Analysis Pipeline tests
├── test_audio_pipeline.py # Audio Processing Pipeline tests
├── test_scene_pipeline.py # Scene Detection Pipeline tests
├── test_person_pipeline.py # Person Tracking Pipeline tests
├── test_audio_speech_pipeline.py # Diarization and Speech Recognition tests
├── test_pipelines.py # Legacy compatibility wrapper (deprecated)
├── test_schemas.py # Schema validation tests
├── test_integration.py # Integration tests
├── test_performance.py # Performance benchmarks
Tests are organized using pytest marks for easy categorization:
-
Unit Tests (
@pytest.mark.unit)- Test individual pipeline components in isolation
- Test configuration validation
- Test error handling
- Mock external dependencies
- Fast execution (< 1 second per test)
-
Integration Tests (
@pytest.mark.integration)- Test component integration with real dependencies
- Test end-to-end pipeline workflows
- Test file I/O operations
- May require external models/services
-
Performance Tests (
@pytest.mark.performance)- Benchmark pipeline performance
- Memory usage testing
- Scalability testing
- Resource consumption validation
-
Schema Tests (in dedicated files)
- Test Pydantic model validation
- Test data serialization/deserialization
- Test schema migrations
The VideoAnnotator test suite uses a modular approach with dedicated test files for each pipeline:
- Face Analysis (
test_face_pipeline.py): Tests face detection, emotion analysis, JSON serialization fixes - Audio Processing (
test_audio_pipeline.py): Tests audio feature extraction, schema validation fixes - Scene Detection (
test_scene_pipeline.py): Tests scene detection and classification - Person Tracking (
test_person_pipeline.py): Tests YOLO integration, tracking, pose estimation - Audio Speech (
test_audio_speech_pipeline.py): Tests diarization and speech recognition
- Focused Testing: Each file contains tests for a single pipeline
- Easier Maintenance: Smaller, focused test files are easier to maintain
- Parallel Execution: Pipeline tests can be run independently
- Clear Responsibilities: Each test file has a clear scope and purpose
# Run tests for a specific pipeline
uv run python -m pytest tests/test_face_pipeline.py -v
# Run specific test categories across all pipelines
uv run python -m pytest tests/ -m unit -v
uv run python -m pytest tests/ -m integration -v
uv run python -m pytest tests/ -m performance -v
# Run all pipeline tests through the test runner
uv run python -m pytest tests/test_all_pipelines.py -v- Test files:
test_*.py - Test classes:
Test*(e.g.,TestScenePipeline) - Test methods:
test_*(e.g.,test_scene_detection_threshold)
class TestPipelineComponent:
"""Test cases for pipeline component."""
def test_initialization(self):
"""Test component initialization."""
# Arrange
config = ComponentConfig(param=value)
# Act
component = Component(config)
# Assert
assert component.config.param == value
def test_process_valid_input(self):
"""Test processing with valid input."""
# Test implementation
pass
def test_process_invalid_input(self):
"""Test error handling with invalid input."""
# Test implementation
passsample_video: Creates temporary test video filessample_audio: Creates temporary test audio filestemp_output_dir: Creates temporary output directoriesmock_models: Mocks ML model dependencies
- Mock External Dependencies: Always mock external APIs, file systems, and ML models
- Use pytest-mock: Prefer
pytest-mockplugin for mocking - Mock at Module Level: Mock imports at the module level when possible
@patch('src.pipelines.scene_detection.cv2')
def test_video_processing(mock_cv2, sample_video):
"""Test video processing with mocked OpenCV."""
# Test implementationStore test data in tests/data/ directory:
tests/data/
├── videos/
│ ├── sample_short.mp4 # 5-second test video
│ └── sample_long.mp4 # 30-second test video
├── audio/
│ ├── sample_speech.wav # Speech audio sample
│ └── sample_music.wav # Music audio sample
└── expected_outputs/
├── scene_results.json # Expected scene detection results
└── person_results.json # Expected person tracking results
- Keep test videos under 10MB
- Keep test audio files under 5MB
- Use compressed formats (H.264, MP3)
- Minimum Coverage: 80% overall
- Pipeline Coverage: 90% for core pipeline code
- Schema Coverage: 95% for data validation code
# Run tests with coverage
pytest --cov=src tests/
# Generate HTML coverage report
pytest --cov=src --cov-report=html tests/
# Check coverage requirements
pytest --cov=src --cov-fail-under=80 tests/- Test with standardized input sizes
- Measure processing time per frame
- Monitor memory usage
- Test on different hardware configurations
@pytest.mark.performance
def test_pipeline_performance(benchmark, sample_video):
"""Benchmark pipeline performance."""
def run_pipeline():
return pipeline.process_video(sample_video)
result = benchmark(run_pipeline)
assert result is not NoneTests should pass in the following environments:
- Python 3.8, 3.9, 3.10, 3.11
- Windows, Linux, macOS
- CPU and GPU environments
# .github/workflows/tests.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: [3.8, 3.9, 3.10, 3.11]
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -r requirements-test.txt
- name: Run tests
run: pytest --cov=src tests/Every test should have a clear docstring explaining:
- What is being tested
- Expected behavior
- Any special setup requirements
def test_scene_detection_threshold(self):
"""
Test scene detection with different threshold values.
Verifies that:
- Higher thresholds result in fewer scene changes
- Lower thresholds result in more scene changes
- Invalid thresholds raise appropriate errors
"""
# Test implementation- Comment complex test setup
- Explain non-obvious assertions
- Document known limitations or edge cases
def test_invalid_video_path(self):
"""Test handling of invalid video paths."""
with pytest.raises(FileNotFoundError):
pipeline.process_video("nonexistent_video.mp4")
def test_invalid_configuration(self):
"""Test configuration validation."""
with pytest.raises(ValueError, match="threshold must be between 0 and 1"):
ScenePipelineConfig(threshold=2.0)Always test:
- Empty inputs
- Null/None values
- Extremely large inputs
- Malformed data
- Network failures (for external APIs)
- Identify the appropriate test file in
tests/ - Add test class if testing a new component
- Add test methods following naming conventions
- Use existing fixtures from
conftest.py - Follow documentation standards
# In tests/test_pipelines.py
class TestNewPipeline:
"""Test cases for new pipeline component."""
def test_new_pipeline_initialization(self):
"""Test new pipeline initialization."""
# Test implementation
def test_new_pipeline_processing(self, sample_video):
"""Test new pipeline video processing."""
# Test implementation- Test First: Write tests before implementing features
- Keep Tests Simple: Each test should focus on one behavior
- Use Descriptive Names: Test names should clearly describe what's being tested
- Mock External Dependencies: Don't test external libraries
- Test Edge Cases: Include boundary conditions and error cases
- Regular Maintenance: Keep tests up to date with code changes
- Performance Awareness: Monitor test execution time
- Documentation: Keep test documentation current
# Run all tests
pytest
# Run specific test file
pytest tests/test_pipelines.py
# Run specific test class
pytest tests/test_pipelines.py::TestScenePipeline
# Run specific test method
pytest tests/test_pipelines.py::TestScenePipeline::test_initialization
# Run with verbose output
pytest -v
# Run with coverage
pytest --cov=src
# Run performance tests only
pytest -m performance# Run tests with debug output
pytest -s --log-cli-level=DEBUG
# Run tests with pdb on failure
pytest --pdb
# Run tests with pytest-xvs for detailed output
pytest -xvsThis testing framework ensures consistent, reliable, and maintainable tests across the VideoAnnotator project.