Testing¶
Running tests¶
# All tests
pytest
# Verbose with coverage
pytest -v --cov=birdnet_stm32
# Skip slow/integration tests
pytest -m "not slow and not integration"
# Single file
pytest tests/test_audio_io.py
Test structure¶
tests/
├── conftest.py # Shared fixtures
├── fixtures/ # Static test data
├── test_activity.py # Activity detection logic
├── test_audio_io.py # Audio loading, resampling, chunking
├── test_augmentation.py # Audio augmentation pipeline
├── test_config.py # ModelConfig serialization
├── test_conversion.py # TFLite conversion pipeline
├── test_dataset.py # File discovery, class handling
├── test_dscnn.py # DS-CNN model building and scaling
├── test_eval_reports.py # Evaluation reporting (species AP, DET, HTML, benchmark)
├── test_focal_loss.py # Focal loss function
├── test_frontend_layer.py # AudioFrontendLayer shapes and modes
├── test_frontend_parity.py # Float/quantized frontend parity
├── test_frontend_registry.py # Frontend name normalization and aliases
├── test_magnitude.py # Magnitude scaling modes (pwl, pcen, db)
├── test_metrics.py # ROC-AUC, cmAP, F1 computation
├── test_optimizer.py # Optimizer configuration
├── test_pooling.py # avg/max/lme pooling
├── test_qat.py # Quantization-aware training
├── test_quantization_sim.py # Quantization simulation utilities
├── test_runners.py # Evaluation runner pipeline
├── test_spec_augment.py # SpecAugment / frequency masking
├── test_spectrogram.py # Spectrogram computation, shapes
├── test_threshold_opt.py # Threshold optimization
└── test_train_to_eval.py # End-to-end train → evaluate integration
Writing tests¶
Conventions¶
- File naming:
test_<module>.pymirroring the source module. - Function naming:
test_<function>_<scenario>, e.g.,test_load_audio_file_mono. - Fixtures: use
conftest.pyfixtures for shared setup (tmp dirs, sample audio, configs). - Markers: use
@pytest.mark.slowfor tests > 5 seconds,@pytest.mark.integrationfor end-to-end tests.
Fixtures from conftest.py¶
| Fixture | Description |
|---|---|
sample_rate |
Default sample rate (22050 Hz) |
chunk_duration |
Default chunk duration (3 seconds) |
mel_bins |
Default number of mel bins (64) |
spec_width |
Default spectrogram width in frames (256) |
fft_length |
Default FFT length (512) |
num_classes |
Default number of classes (10) |
sine_wave |
1 kHz sine wave (float32 array) |
silence |
All-zeros signal |
white_noise |
Random white noise (seeded) |
tmp_dataset |
Temp directory with class_a/class_b WAV files |
TensorFlow-dependent tests¶
Some tests require TensorFlow, which may not be available in all environments.
Use pytest.importorskip:
This skips the test gracefully if TF is not installed rather than failing.
Adding a new test¶
- Create
tests/test_<module>.py. - Import the module under test.
- Use fixtures from
conftest.pywhere applicable. - Add appropriate markers (
@pytest.mark.slow, etc.). - Run:
pytest tests/test_<module>.py -v