Skip to content

Add a hardware-free pytest suite and a minimal CI workflow - #4

Open
egeboy35 wants to merge 1 commit into
lkk688:mainfrom
egeboy35:test/pytest-ci
Open

Add a hardware-free pytest suite and a minimal CI workflow#4
egeboy35 wants to merge 1 commit into
lkk688:mainfrom
egeboy35:test/pytest-ci

Conversation

@egeboy35

@egeboy35 egeboy35 commented Aug 18, 2026

Copy link
Copy Markdown

This PR adds a small automated test suite and CI setup for the pure-DSP parts of the repository.

Most existing test_*.py scripts cannot run unattended. Measured in a plain numpy/scipy/matplotlib environment, 22 of the 33 fail at pytest collection: 7 need pyadi-iio, 1 needs torch, 1 cv2, 1 PyQt6, and 12 fail only because the flat-layout modules (sdr_video_comm, myadiclass and friends) are not importable from the repository root. So regressions in the math-only paths were easy to miss.

What's included

  • tests/ — 22 pytest tests, all hardware-free and deterministic (seeded RNGs, first-principles golden values): OFDM/OTFS modulate-demodulate loopbacks and flat-channel equalization, convolutional FEC (Viterbi) round trip and error correction, Schmidl-Cox preamble sync on a delayed/rotated/noisy signal, the RF packet protocol (CRC32 framing, chunking) and QPSK Gray mapping, the 802.11a LTF autocorrelation, the OFDM FFT-shift convention, and AIRadarLib (radar parameter derivation, chirp/tone spectra, CA-CFAR detection, target masks, noise SNR calibration).
  • Torch-optional — the 5G LDPC round trip and the CFAR tests gate on pytest.importorskip("torch") and skip cleanly when torch is absent; the LDPC test is marked slow (-m "not slow" deselects it). Without torch the suite reports 19 passed and 2 skipped of the 22 (the two skips cover 3 test functions, since one module skips at collection).
  • tests/conftest.py — sets MPLBACKEND=Agg before any matplotlib import, reconfigures stdout to UTF-8 (some modules print Unicode that breaks Windows cp125x consoles), and derives the sdradi/pluto_test/AIRadar sys.path entries from __file__.
  • .github/workflows/ci.yml — a lint job and a test job on Python 3.11 with the CPU-only torch wheel. Three deliberate choices: the compileall syntax guard runs before the linter so a style finding cannot mask a real syntax regression; ruff is pinned so a future release cannot turn CI red without a code change; and push builds are limited to main so pull requests are not built twice.
  • pytest.ini / requirements-dev.txt — restrict collection to tests/ (the hardware and flat-layout scripts elsewhere are never collected) and list the test dependencies.

Everything is additive: no existing file is modified.

Verified locally with ruff 0.16.3 (clean over tests/), compileall (exit 0 over all six packages), and pytest. I also checked the gates against my other open PRs by merging them together locally: #1..#8 merge without conflict and the lint and test gates both pass on the merged tree, so this workflow should not paint the other PRs red.

If a workflow file under .github/ from an outside contributor is not something you want to take on, the tests/ directory stands on its own — happy to drop the CI half.

🤖 Generated with Claude Code

Most existing test_*.py scripts in the repository cannot run unattended: in a
plain numpy/scipy/matplotlib environment 22 of the 33 fail at pytest
collection -- 7 need pyadi-iio, 1 torch, 1 cv2, 1 PyQt6, and 12 fail only
because the flat-layout modules (sdr_video_comm, myadiclass and friends) are
not importable from the repository root. So regressions in the pure-DSP code
paths were easy to miss.

Added:

- tests/: 22 pytest tests, all hardware-free and deterministic (seeded RNGs,
  first-principles golden values): OFDM/OTFS modulate-demodulate loopbacks and
  flat-channel equalization, convolutional FEC (Viterbi) round trip and error
  correction, Schmidl-Cox preamble sync on a delayed/rotated/noisy signal, the
  RF packet protocol (CRC32 framing, chunking) and QPSK Gray mapping, the
  802.11a LTF autocorrelation, the OFDM FFT-shift convention, and AIRadarLib
  (radar parameter derivation, chirp/tone spectra, CA-CFAR detection, target
  masks, noise SNR calibration).
- Torch-optional: the 5G LDPC round trip and the CFAR tests gate on
  pytest.importorskip("torch") and skip cleanly when torch is absent; the LDPC
  test is marked slow (-m "not slow" deselects it). Without torch the suite
  reports 19 passed and 2 skipped of the 22.
- tests/conftest.py: sets MPLBACKEND=Agg before any matplotlib import,
  reconfigures stdout to UTF-8 (some modules print Unicode that breaks Windows
  cp125x consoles), and derives the sdradi/pluto_test/AIRadar sys.path entries
  from __file__.
- .github/workflows/ci.yml: a lint job (compileall syntax guard over the six
  Python packages, then ruff over tests/) and a test job on Python 3.11 with
  the CPU-only torch wheel. The syntax check runs before the linter so a style
  finding cannot mask a real syntax regression, ruff is pinned so a future
  release cannot turn CI red without a code change, and push builds are limited
  to main so pull requests are not built twice.
- pytest.ini / requirements-dev.txt: restrict collection to tests/ (the
  hardware and flat-layout scripts elsewhere are never collected) and list the
  test dependencies.

Everything is additive: no existing file is modified. Verified locally with
ruff 0.16.3 (clean over tests/), compileall (exit 0 over all six packages),
and pytest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant