Skip to content

Add property-based tests with hypothesis for analysis invariants #17

Description

@mfeeney

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpriority:lowWorth tracking, low immediate ROI

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions