Restructures tests/hardware/ so that fixture access is controlled by
directory layout — pytest only walks upward through conftest.py files,
so a PSU test physically cannot request fio/alm/nad.
Layout:
- tests/hardware/conftest.py (unchanged: PSU fixtures)
- tests/hardware/mum/conftest.py NEW: _require_mum (session autouse),
fio (session), nad (session),
alm (session), _reset_to_off
(function autouse)
- tests/hardware/mum/** MUM tests + swe5/ + swe6/
- tests/hardware/psu/** PSU-only tests
- tests/hardware/babylin/** deprecated BabyLIN E2E
What this removes (was duplicated before):
- 7 verbatim copies of the `fio` fixture
- 6 copies of the `alm` fixture
- 6 copies of the `_reset_to_off` autouse
- 9 inline `if config.interface.type != "mum": pytest.skip(...)` gates
What this changes by design:
- fio / alm / nad scope: module → session. NAD discovery happens once
per run instead of once per module. The helpers are immutable beyond
their constructor args, so sharing them is safe; per-test state is
reset by the autouse `_reset_to_off`.
- test_overvolt.py: `_park_at_nominal` is now `_reset_to_off`, which
cleanly overrides the conftest's LED-only version (PSU + LED reset).
- test_mum_alm_animation_generated.py keeps a local `_reset_to_off` +
`_force_off` so its "no AlmTester anywhere" demonstration is preserved
via fixture override; the local `nad` is also retained because it
uses the typed `AlmStatus.receive` API.
Docs:
- docs/24_test_wiring.md NEW — describes the three-layer fixture
topology, lifecycle sequence diagram, helper class wiring, and the
playbook for adding a new framework component.
- docs/05_architecture_overview.md: add MCF (mum conftest) node to the
Mermaid diagram + mention it in the components list.
- docs/19_frame_io_and_alm_helpers.md: replace the per-module
fixture-wiring example with a request-fixtures-by-name snippet plus
the override pattern.
- Path references swept across docs/02, docs/14, docs/18, docs/20,
docs/README to point at the new locations.
Verified: pytest --collect-only collects 93 tests with no errors;
30 unit tests and 10 mock-only smoke tests pass; fixture-per-test
output shows PSU tests cannot see fio/alm/nad.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.5 KiB
6.5 KiB
Configuration Resolution: What is read and when
This document explains how configuration is loaded, merged, and provided to tests and interfaces.
Looking for the implementation deep-dive — merge semantics, type coercion, the forward-reference quirk in
EcuTestConfig, and the PSU side-channel? See23_config_loader_internals.md.
Sources and precedence
From highest to lowest precedence:
- In-code overrides (if
load_config(..., overrides=...)is used) - Environment variable
ECU_TESTS_CONFIG(absolute/relative path to YAML) config/test_config.yaml(if present under the workspace root)- Built-in defaults
Data model (dataclasses)
EcuTestConfiginterface: InterfaceConfigtype:mock,mum, orbabylin(deprecated)channel: LIN channel index (0-based in SDK wrapper) — BabyLIN-specific (deprecated)bitrate: LIN baudrate (e.g., 19200). The MUM uses this directly; BabyLIN typically takes it from the SDF (deprecated path)sdf_path: Path to SDF file (BabyLIN; deprecated — required for typical BabyLIN operation)schedule_nr: Schedule number to start on connect (BabyLIN; deprecated).-1= skipnode_name: Optional node identifier (informational)dll_path,func_names: Deprecated legacy fields from the old ctypes adapter; not used with the SDK wrapperhost: MUM IP address (MUM-only). Required whentype: mumlin_device: MUM LIN device name (MUM-only, defaultlin0)power_device: MUM power-control device (MUM-only, defaultpower_out0)boot_settle_seconds: Delay after MUM power-up before sending the first frame (default 0.5)frame_lengths: Optional{frame_id: data_length}map for the MUM adapter to drive slave-published reads. Hex keys like0x0Aare supported in YAML. Whenldf_pathis set, this acts as an override on top of LDF-derived lengths.ldf_path: Optional path to a.ldffile. Tests can request theldffixture to obtain anLdfDatabasefor per-framepack/unpack; the MUM adapter additionally inherits frame lengths from the LDF. Relative paths resolve against the workspace root
flash: FlashConfigenabled: whether to flash before testshex_path: path to HEX file
power_supply: PowerSupplyConfigenabled: whether PSU features/tests are activeport: Serial device (e.g.,COM4,/dev/ttyUSB0)baudrate,timeout,eol: line settings (e.g.,"\n"or"\r\n")parity:N|E|Ostopbits:1or2xonxoff,rtscts,dsrdtr: flow control flagsidn_substr: optional substring to assert in*IDN?do_set,set_voltage,set_current: optional demo/test actions
YAML examples
Minimal mock configuration (default):
interface:
type: mock
channel: 1
bitrate: 19200
flash:
enabled: false
Hardware via MUM (current default) — see also config/mum.example.yaml:
interface:
type: mum
host: 192.168.7.2 # MUM IP address (USB-RNDIS default)
lin_device: lin0 # MUM LIN device name
power_device: power_out0 # MUM power-control device
bitrate: 19200 # LIN baudrate
boot_settle_seconds: 0.5 # Delay after power-up before first frame
frame_lengths:
0x0A: 8 # ALM_Req_A
0x11: 4 # ALM_Status
flash:
enabled: false
Hardware (BabyLIN SDK wrapper) configuration — DEPRECATED, prefer the MUM example above:
interface:
type: babylin # deprecated
channel: 0 # 0-based channel index
bitrate: 19200 # optional; typically driven by SDF
node_name: "ECU_TEST_NODE"
sdf_path: "./vendor/Example.sdf"
schedule_nr: 0
flash:
enabled: true
hex_path: "firmware/ecu_firmware.hex"
Power supply configuration (either inline or merged from a dedicated YAML):
```yaml
power_supply:
enabled: true
port: COM4 # or /dev/ttyUSB0 on Linux
baudrate: 115200
timeout: 1.0
eol: "\n" # or "\r\n" if your device requires CRLF
parity: N # N|E|O
stopbits: 1 # 1|2
xonxoff: false
rtscts: false
dsrdtr: false
idn_substr: OWON
do_set: false
set_voltage: 5.0
set_current: 0.1
## Load flow
```text
tests/conftest.py: config() fixture
→ load_config(workspace_root)
→ check env var ECU_TESTS_CONFIG
→ else check config/test_config.yaml
→ else use defaults
→ convert dicts to EcuTestConfig dataclasses
→ provide to other fixtures/tests
Additionally, if present, a dedicated PSU YAML is merged into `power_supply`:
- Environment variable `OWON_PSU_CONFIG` (path to YAML), else
- `config/owon_psu.yaml` under the workspace root
This lets you keep machine-specific serial settings separate while still having
central defaults in `config/test_config.yaml`.
How tests and adapters consume config
linfixture picksmock,mum, orbabylin(deprecated) based oninterface.type- Mock adapter uses
bitrateandchannelto simulate timing/behavior - MUM adapter uses
host,lin_device,power_device,bitrate,boot_settle_seconds, andframe_lengthsto open the MUM, set up the LIN bus, and power up the ECU on connect - BabyLIN adapter (SDK wrapper, DEPRECATED) uses
sdf_path,schedule_nr,channelto open the device, load the SDF, and start a schedule.bitrateis informational unless explicitly applied via commands/SDF. Selectinginterface.type: babylinemits aDeprecationWarning. flash_ecuusesflash.enabledandflash.hex_path- PSU-related tests or utilities read
config.power_supplyfor serial parameters and optional actions (IDN assertions, on/off toggle, set/measure). The reference implementation isecu_framework/power/owon_psu.py, with a hardware test intests/hardware/psu/test_owon_psu.pyand a quick demo script invendor/Owon/owon_psu_quick_demo.py.
Tips
- Keep multiple YAMLs and switch via
ECU_TESTS_CONFIG - Check path validity for
sdf_pathandhex_pathbefore running hardware tests - For the deprecated BabyLIN path only: ensure
vendor/BabyLIN_library.pyand the platform-specific libraries from the SDK are available onPYTHONPATH - Use environment-specific YAML files for labs vs. CI
- For PSU, prefer
OWON_PSU_CONFIGorconfig/owon_psu.yamlto avoid committing local COM port settings. Central defaults can live inconfig/test_config.yaml.