2 Commits

Author SHA1 Message Date
08247f9321 refactor(tests): AlmTester as the single contributor-facing API
Extends ``tests/hardware/alm_helpers.py`` into the full surface that
hardware tests use, so contributors write intent (``alm.send_color``,
``alm.read_led_state``, ``alm.wait_for_led_on``) and never touch
``fio.send("ALM_Req_A", AmbLight…=…)`` or LDF schema details.

What landed:

- AlmTester gains ~16 methods:
    read_nad, read_voltage_status, read_thermal_status, read_nvm_status,
    read_sig_comm_err, read_ntc_kelvin, read_ntc_celsius, read_pwm,
    read_pwm_wo_comp, send_color, send_color_broadcast, save_color,
    apply_saved_color, discard_saved_color, send_config, plus
    wait_for_led_on / wait_for_led_off / wait_for_animating wrappers.
- The six IntEnum classes that ALM tests need (LedState, Mode, Update,
  NVMStatus, VoltageStatus, ThermalStatus) are defined directly in
  alm_helpers.py — tests get them via `from alm_helpers import …`.
- All ALM test files migrated:
    test_mum_alm_animation.py, test_mum_alm_cases.py, test_overvolt.py,
    swe5/test_anm_management.py, swe5/test_com_management.py
    each now go through AlmTester for every common pattern.
- swe6/test_com_management.py: stays on `fio` (these tests probe
  schema features not in the current production LDF and skip when
  the LDF doesn't declare them) — change limited to LedState enum.
- test_mum_alm_animation_generated.py deleted — its "no-AlmTester"
  demonstration loses its point now that AlmTester is the
  recommended path.
- docs/19_frame_io_and_alm_helpers.md reframed: AlmTester is the
  contributor surface; FrameIO is implementation detail. New API
  reference + Cookbook examples + a note that the maintenance pact
  is "LDF changes → AlmTester updates".

Verified: pytest --collect-only collects 87 tests cleanly; 40 unit
+ mock smoke tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 01:23:52 +02:00
f5a4ba532b tests/hardware: add FrameIO + AlmTester helper layer
Splits hardware-test concerns into two reusable modules and rebuilds
test_mum_alm_animation.py on top of them.

- frame_io.py — generic LDF-driven I/O class. Knows nothing about
  ALM. Three access levels:
    high: send/receive/read_signal by frame and signal name
    mid:  pack/unpack — bytes ↔ signals without I/O
    low:  send_raw/receive_raw — bypass the LDF entirely
  Plus introspection: frame, frame_id, frame_length. Frame lookups
  are cached per FrameIO instance.

- alm_helpers.py — ALM_Node domain helpers built on FrameIO.
  AlmTester class bound to (fio, nad) exposes:
    force_off, read_led_state, wait_for_state,
    measure_animating_window, assert_pwm_matches_rgb,
    assert_pwm_wo_comp_matches_rgb
  Plus pure utilities (ntc_kelvin_to_celsius, pwm_within_tol) and
  the LED-state / pacing / PWM-tolerance constants. PWM assertions
  use vendor/rgb_to_pwm.py (compute_pwm) at the runtime
  Tj_Frame_NTC temperature.

- test_mum_alm_animation.py rewritten:
    * fio + alm fixtures replace the previous dict-based _ctx
    * SETUP / PROCEDURE / ASSERT / TEARDOWN section markers
    * test_mode1_fade now wraps its ConfigFrame change in
      try/finally so EnableCompensation is restored even on
      assertion failure (was leaking state into later tests)
    * test_disable_compensation_pwm_wo_comp uses the four-phase
      pattern explicitly

Sibling imports work because pytest's default rootdir mode puts the
test file's directory on sys.path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:00:36 +02:00