Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Testing Guide

The four layers

LayerWhereRun with
Rust unit testsinline #[cfg(test)] modules in every crate's src/cargo test --all
In-process protocol/integration testsspvirit-tools/tests/ (30 test files + shared harnesses, ~100 test fns), plus per-crate tests/ integration suites in spvirit-client, -server, -ioc, -gateway and -calccargo test -p spvirit-tools (or -p <crate>)
Cross-implementation interop testsspvirit-tools/tests/interop_*.rs + tests/interop/env-gated; see below
Python testsspvirit-py/tests/test_*.py (6 files)run each file directly with the venv python (test_ioc_host_api.py: python -m pytest)
spvirit-py embedded-interpreter unit testsspvirit-py/src/cargo test -p spvirit-py --no-default-features --features test-embed

There are no benchmarks (no benches/, no criterion). There is a small set of golden spec vectors (spvirit-tools/tests/protocol/spec_vectors/*.bin, 9 files, decoded by golden_spec_vectors_decode), but no corpus of packet captures from real servers. Most codec tests are inline-bytes and round-trip based.

Rust unit tests

Every crate keeps tests at the bottom of each source file. Notable suites:

  • spvirit-codec: spvd_encode (39), spvd_decode (38), spvirit_encode (25), epics_decode (19), monitor (12), segment (11), error (6).
  • spvirit-server: simple_store (MDEL, timestamps, all 12 array element types, put_nt, validator rejection), pv (constructors, attach guards), pva_server (builder wiring, links), monitor (delta-frame semantics), db, record_fields, group.
  • spvirit-client: ~130 tests (search target math, parsing, cache/pool and retry behaviour, round-trips).

In-process protocol tests (spvirit-tools/tests/)

Two harnesses under tests/protocol/:

  • frame_harness.rs — TestServer/TestSession: spawns actual workspace binaries (locates target/<profile>/) and speaks raw frames.
  • scenario_harness.rs — ScenarioSession: higher-level connect/handshake/get/put helpers.

Used by spvirit_protocol_* (codec, lifecycle, matrix, unsupported-command handling), spvirit_pvlist, spvirit_monitor_fields (nested pvRequest selection), spvirit_monitor_pipeline (flow control), spvirit_put_timestamp, spvirit_server_startup and spvirit_explore_client. Other integration files (ioc_fields, pv_handle_api, spvirit_nt_lifecycle, spvirit_record_array, spvirit_search_resilience, spvirit_get incl. read-only/simulation PUT authorization) start their own server process and drive it through the client library.

Interop tests (against real EPICS implementations)

tests/interop/harness.rs provides ProcessGuard, LocalServerFixture, free-port helpers, and sets EPICS_PVA_ADDR_LIST=127.0.0.1, EPICS_PVA_AUTO_ADDR_LIST=NO, EPICS_PVA_BROADCAST_PORT for hermetic runs.

All interop tests are env-gated and skip silently unless enabled:

SuiteNeedsEnable
p4p (pvxs)pip install p4pPVA_TEST_P4P=1, P4P_PROVIDER_CMD → tests/interop/p4p_server.py, P4P_TEST_SERVER=127.0.0.1:5075
EPICS BaseEPICS Base installits own enable vars (see interop_epics_base.rs)
PVAccessJavaGradle projectsee interop_pvaccess_java.rs
Generic external serverany PVA serverPVA_TEST_SERVER, PVA_TEST_PV, PVA_TEST_MONITOR, PVA_TEST_* addr/port vars

CI runs the p4p matrix on every push/PR (see chapter 07). The command:

PVA_TEST_P4P=1 P4P_PROVIDER_CMD="python spvirit-tools/tests/interop/p4p_server.py" \
  cargo test -p spvirit-tools --test interop_tool_matrix -- p4p_provider_matrix

Python tests

Five of the six files are plain-assert scripts with a __main__ loop that calls every test_* function, run directly with the venv's python. The exception is test_ioc_host_api.py, which uses pytest.raises and must be run with python -m pytest tests/test_ioc_host_api.py. Conventions:

  • Every test that starts a Server uses its own unique port pair (test_pv_handles.py: 15075–15246; test_value_types.py: 16060–16083, within its reserved 16060–16099 range). Pick unused ranges for new files.
  • Build first: .\.venv\Scripts\maturin.exe develop (debug is fine).
  • Run: .\.venv\Scripts\python.exe tests\test_pv_handles.py → expect ALL OK.

Conventions for new work

  • TDD is the house style: write the failing test first, verify it fails, implement, verify it passes, commit per task. Follow the same rhythm.
  • Timestamps in tests: always set explicit NtTimeStamps on payloads you assert against — a None timestamp is stamped at encode time and makes monitor-delta assertions flaky (see chapter 02).
  • When touching the codec, remember the four duplicated size codecs and the absence of a capture corpus — add a round-trip test in the same file as the change, and consider checking real captures from pvxs/p4p if the change is wire-visible.