Problem
The current test suite validates specific synthesized signals against expected outputs, but doesn't cover algorithmic invariants. For example: a signal scaled by 2x should be exactly 6 dB louder; a stereo signal with identical L/R channels should have correlation == 1.0; flipping the polarity of one channel should flip the polarity flag in analyze_phase.
These are properties that should hold for any valid input, and they're exactly the kind of thing property-based testing catches.
Why it's a problem
Property-based tests catch a class of bugs that example-based tests miss — particularly around boundary conditions, near-silent inputs, unusual sample-rate combinations, and signals with extreme dynamic range. For a DSP library, this is high-value coverage with low maintenance cost.
Suggested approach
Add hypothesis>=6.0 as a dev dep and write invariant tests, e.g.:
from hypothesis import given, strategies as st
@given(scale=st.floats(min_value=0.1, max_value=0.9))
def test_loudness_scales_logarithmically(scale, sine_1khz_minus23lufs):
a = analyze_loudness(sine_1khz_minus23lufs)
scaled = AudioData(samples=sine_1khz_minus23lufs.samples * scale, ...)
b = analyze_loudness(scaled)
expected_delta = 20 * np.log10(scale)
assert abs((b.integrated_lufs - a.integrated_lufs) - expected_delta) < 0.1
Other invariants to cover:
- Time-reversed signal: spectrum is identical (within FFT precision); phase polarity unchanged.
- Mono → duplicated stereo: correlation == 1.0, width == 0.
- Mono → polarity-flipped stereo: correlation == -1.0.
- Concatenating silence at the start: integrated LUFS shifts predictably with relative gating duration.
- DC-offset signal:
detect_problems flags DC offset.
Verification
- New file
tests/test_invariants.py with hypothesis-based tests.
- All invariants pass on the current implementation, OR a real bug is revealed (file separately).
- CI runs hypothesis with
--hypothesis-seed=0 for reproducibility, plus a nightly job with random seeds for broader coverage.
Problem
The current test suite validates specific synthesized signals against expected outputs, but doesn't cover algorithmic invariants. For example: a signal scaled by 2x should be exactly 6 dB louder; a stereo signal with identical L/R channels should have correlation == 1.0; flipping the polarity of one channel should flip the polarity flag in
analyze_phase.These are properties that should hold for any valid input, and they're exactly the kind of thing property-based testing catches.
Why it's a problem
Property-based tests catch a class of bugs that example-based tests miss — particularly around boundary conditions, near-silent inputs, unusual sample-rate combinations, and signals with extreme dynamic range. For a DSP library, this is high-value coverage with low maintenance cost.
Suggested approach
Add
hypothesis>=6.0as a dev dep and write invariant tests, e.g.:Other invariants to cover:
detect_problemsflags DC offset.Verification
tests/test_invariants.pywith hypothesis-based tests.--hypothesis-seed=0for reproducibility, plus a nightly job with random seeds for broader coverage.