# ECU Tests Framework Python-based ECU testing framework built on pytest, with a pluggable LIN communication layer (Mock and MUM, with the deprecated BabyLIN adapter retained for backward compatibility), configuration via YAML, and enhanced HTML/XML reporting with rich test metadata. > **Heads-up:** the BabyLIN adapter is **deprecated**. New tests and deployments should target MUM. BabyLIN is documented below only so existing setups can keep running while they migrate. ## Highlights - **MUM (Melexis Universal Master) adapter** — current default for hardware tests; networked LIN master with built-in power control - Mock LIN adapter for fast, hardware-free development - BabyLIN adapter (DEPRECATED) using the vendor SDK's Python wrapper - Hex flashing scaffold you can wire to UDS - Rich pytest fixtures and example tests - Self-contained HTML report with Title, Requirements, Steps, and Expected Results extracted from test docstrings - JUnit XML report for CI/CD ## Quick links - Using the framework (common runs, markers, CI, Pi): `docs/12_using_the_framework.md` - Plugin overview (reporting, hooks, artifacts): `docs/11_conftest_plugin_overview.md` - Power supply (Owon) usage and troubleshooting: `docs/14_power_supply.md` - Report properties cheatsheet (standard keys): `docs/15_report_properties_cheatsheet.md` - MUM source scripts (vendor reference): [vendor/automated_lin_test/README.md](vendor/automated_lin_test/README.md) ## TL;DR quick start (copy/paste) Mock (no hardware): ```powershell python -m venv .venv; .\.venv\Scripts\Activate.ps1; pip install -r requirements.txt; pytest -m "not hardware" -v ``` Hardware via MUM (current default): ```powershell # 1. Install Melexis 'pylin' and 'pymumclient' (see vendor/automated_lin_test/install_packages.sh) # 2. Make sure the MUM is reachable (default IP 192.168.7.2) $env:ECU_TESTS_CONFIG = ".\config\mum.example.yaml"; pytest -m "hardware and mum" -v ``` Hardware via BabyLIN (DEPRECATED — kept for existing rigs only): ```powershell # Place BabyLIN_library.py and native libs under .\vendor per vendor/README.md first $env:ECU_TESTS_CONFIG = ".\config\babylin.example.yaml"; pytest -m "hardware and babylin" -v ``` ## Quick start (Windows PowerShell) 1) Create a virtual environment and install dependencies ```powershell python -m venv .venv .\.venv\Scripts\Activate.ps1 pip install -r requirements.txt ``` 2) Run the mock test suite (default interface) ```powershell python.exe -m pytest -m "not hardware" -v ``` 3) View the reports - HTML: `reports/report.html` - JUnit XML: `reports/junit.xml` Tip: You can change output via `--html` and `--junitxml` CLI options. ## Quick start (WSL on Windows) Use this approach when running from **Windows Subsystem for Linux** instead of PowerShell. ### 1. Open a WSL terminal and navigate to the project Clone or access the repo from within WSL. If the project lives on the Windows filesystem (e.g. `C:\Users\you\ecu-tests`), it is available at: ```bash cd /mnt/c/Users//ecu-tests ``` ### 2. Create a virtual environment and install dependencies ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ### 3. Run the mock test suite (no hardware needed) ```bash python -m pytest -m "not hardware" -v ``` ### 4. Install Melexis packages into the venv (required for hardware tests) `pylin`, `pymumclient`, and `pylinframe` are not on PyPI — they ship with the Melexis IDE. On Windows they live at: ``` C:\Program Files\Melexis\Melexis IDE\plugins\com.melexis.mlxide.python_1.2.0.202408130945\python\Lib\site-packages ``` which WSL exposes at `/mnt/c/Program Files/Melexis/Melexis IDE/...`. **With your venv already activated**, copy the packages directly into it: ```bash source .venv/bin/activate # skip if already active MELEXIS_SITE="/mnt/c/Program Files/Melexis/Melexis IDE/plugins/com.melexis.mlxide.python_1.2.0.202408130945/python/Lib/site-packages" VENV_SITE=$(python -c "import site; print(site.getsitepackages()[0])") cp -r "$MELEXIS_SITE/pylin" "$VENV_SITE/" cp -r "$MELEXIS_SITE/pymumclient" "$VENV_SITE/" cp -r "$MELEXIS_SITE/pylinframe" "$VENV_SITE/" ``` Verify the installation: ```bash python -c "import pylin; import pymumclient; print('OK')" ``` > **Alternative:** You can also run `bash vendor/automated_lin_test/install_packages.sh` after updating the `MELEXIS_SITE_PACKAGES` path in that script — but the commands above are simpler and target the venv directly. ### 5. Run hardware tests via MUM ```bash export ECU_TESTS_CONFIG=./config/mum.example.yaml python -m pytest -m "hardware and mum" -v ``` ### 6. Run hardware tests via BabyLIN (DEPRECATED) > **Deprecated.** The BabyLIN adapter is kept for backward compatibility only; new work should target MUM (step 5). The BabyLIN SDK also ships Windows-only native libraries (`.dll`), so these tests cannot run under WSL unless you have a Linux-compatible `.so` build of the SDK. ```bash export ECU_TESTS_CONFIG=./config/babylin.example.yaml python -m pytest -m "hardware and babylin" -v ``` ### 7. View reports Open the HTML report directly in Windows from the WSL terminal: ```bash explorer.exe reports/report.html ``` Or from PowerShell/CMD: ```powershell start .\reports\report.html ``` --- ## Reporting: Metadata in HTML We extract these fields from each test’s docstring and render them in the HTML report: - Title - Description - Requirements (e.g., REQ-001) - Test Steps - Expected Result Markers like `smoke`, `hardware`, and `req_00x` are also displayed. Example docstring format used by the plugin: ```python """ Title: Mock LIN Interface - Send/Receive Echo Test Description: Validates basic send/receive functionality using the mock LIN interface with echo behavior. Requirements: REQ-001, REQ-003 Test Steps: 1. Connect to mock interface 2. Send frame ID 0x01 with data [0x55] 3. Receive the echo within 100ms 4. Assert ID and data integrity Expected Result: - Echoed frame matches sent frame """ ``` ## Configuration Default config is `config/test_config.yaml`. Override via the `ECU_TESTS_CONFIG` environment variable. ```powershell $env:ECU_TESTS_CONFIG = (Resolve-Path .\config\test_config.yaml) ``` ### MUM configuration (default for hardware) Template: `config/mum.example.yaml` ```yaml interface: type: mum host: 192.168.7.2 # MUM IP (USB-RNDIS default) lin_device: lin0 # MUM LIN device name power_device: power_out0 # MUM power-control device (built-in PSU) bitrate: 19200 # LIN baudrate boot_settle_seconds: 0.5 # Wait after power-up before sending the first frame frame_lengths: 0x0A: 8 # ALM_Req_A 0x11: 4 # ALM_Status ``` The MUM has its own power output, so `power_supply.enabled: false` is the typical setting when using MUM. The Owon PSU support remains for over/under- voltage scenarios but is independent of the LIN interface. ### BabyLIN configuration (DEPRECATED) > Retained for backward compatibility. Prefer the MUM configuration above. Template: `config/babylin.example.yaml` ```yaml interface: type: babylin # deprecated; prefer "mum" or "mock" channel: 0 # Channel index used by the SDK wrapper bitrate: 19200 # Usually determined by SDF sdf_path: ./vendor/Example.sdf schedule_nr: 0 # Start this schedule on connect (-1 to skip) ``` ### LIN adapter capabilities | Adapter | Power control | Diagnostic frames (Classic checksum) | Passive listen | | --- | --- | --- | --- | | `mock` | n/a | n/a | yes (queue-based) | | `mum` | yes (`power_out0`) | yes (`MumLinInterface.send_raw()` → `ld_put_raw`) | no — `receive(id)` triggers a slave read | | `babylin` (deprecated) | external (Owon PSU) | via SDF / `BLC_sendCommand` | yes (frame queue) | Switch to hardware profile and run only hardware tests (MUM example): ```powershell $env:ECU_TESTS_CONFIG = (Resolve-Path .\config\mum.example.yaml) python.exe -m pytest -m hardware -v ``` ## Project structure ``` ecu_tests/ ├── ecu_framework/ # Core framework package │ ├── config.py # YAML config loader → typed dataclasses │ ├── lin/ │ │ ├── base.py # LinInterface + LinFrame contract │ │ ├── mock.py # Mock LIN adapter (no hardware) │ │ ├── mum.py # MUM adapter (current default; Melexis pylin/pymumclient) │ │ ├── ldf.py # LdfDatabase wrapper around ldfparser │ │ └── babylin.py # DEPRECATED BabyLIN SDK-wrapper adapter │ ├── power/ │ │ └── owon_psu.py # Owon PSU SCPI controller + cross-platform port resolver │ └── flashing/ │ └── hex_flasher.py # Hex flashing scaffold │ ├── tests/ │ ├── conftest.py # Project-wide fixtures: config, lin, ldf, flash_ecu, rp │ │ │ ├── unit/ # Pure-logic tests (no hardware) │ │ ├── test_config_loader.py │ │ ├── test_linframe.py │ │ ├── test_ldf_database.py │ │ ├── test_hex_flasher.py │ │ ├── test_mum_adapter_mocked.py │ │ └── test_babylin_adapter_mocked.py # deprecated path │ │ │ ├── plugin/ │ │ └── test_conftest_plugin_artifacts.py # reporting plugin self-test │ │ │ ├── hardware/ # Real-bench tests (MUM / PSU / ECU) │ │ ├── conftest.py # Session-scoped autouse PSU fixture (powers the ECU) │ │ ├── frame_io.py # FrameIO — generic LDF-driven send/receive/pack/unpack │ │ ├── alm_helpers.py # AlmTester — ALM_Node domain helpers + constants │ │ ├── psu_helpers.py # apply_voltage_and_settle — measure-rail-then-validate │ │ ├── _test_case_template.py # ALM-only test starting point (not collected) │ │ ├── _test_case_template_psu_lin.py # PSU + LIN test starting point (not collected) │ │ ├── test_mum_alm_animation.py # ALM mode/update/LID checks via MUM │ │ ├── test_mum_auto_addressing.py # BSM auto-addressing (NAD) │ │ ├── test_e2e_mum_led_activate.py # MUM end-to-end power+activate │ │ ├── test_overvolt.py # Voltage-tolerance (over/under/sweep) │ │ ├── test_psu_voltage_settling.py # PSU settling-time characterization (-m psu_settling) │ │ ├── test_owon_psu.py # PSU IDN + measurements (read-only) │ │ └── test_e2e_power_on_lin_smoke.py # DEPRECATED BabyLIN E2E │ │ │ ├── test_smoke_mock.py # Mock interface smoke + boundary │ ├── test_babylin_hardware_smoke.py # DEPRECATED BabyLIN hardware │ ├── test_babylin_hardware_schedule_smoke.py # DEPRECATED BabyLIN schedule flow │ ├── test_babylin_wrapper_mock.py # DEPRECATED BabyLIN adapter w/ mock wrapper │ └── test_hardware_placeholder.py │ ├── config/ │ ├── test_config.yaml # Default config (MUM by default) │ ├── mum.example.yaml # MUM hardware profile │ ├── owon_psu.example.yaml # PSU profile (copy to owon_psu.yaml) │ ├── owon_psu.yaml # Optional per-machine PSU override │ ├── examples.yaml # Combined mock/babylin profiles │ └── babylin.example.yaml # DEPRECATED BabyLIN profile │ ├── docs/ │ ├── README.md # Documentation index │ ├── 01_run_sequence.md # End-to-end run sequence │ ├── 02_configuration_resolution.md │ ├── 03_reporting_and_metadata.md │ ├── 04_lin_interface_call_flow.md │ ├── 05_architecture_overview.md │ ├── 06_requirement_traceability.md │ ├── 07_flash_sequence.md │ ├── 08_babylin_internals.md # DEPRECATED │ ├── 09_raspberry_pi_deployment.md │ ├── 10_build_custom_image.md │ ├── 11_conftest_plugin_overview.md │ ├── 12_using_the_framework.md │ ├── 13_unit_testing_guide.md │ ├── 14_power_supply.md # PSU controller, resolver, session-managed power │ ├── 15_report_properties_cheatsheet.md │ ├── 16_mum_internals.md │ ├── 17_ldf_parser.md │ ├── 18_test_catalog.md │ ├── 19_frame_io_and_alm_helpers.md # Hardware test helpers + four-phase pattern │ └── DEVELOPER_COMMIT_GUIDE.md │ ├── vendor/ # Third-party + project assets │ ├── 4SEVEN_color_lib_test.ldf # LDF used by the LIN tests │ ├── 4SEVEN_color_lib_test.sdf # SDF for the deprecated BabyLIN path │ ├── rgb_to_pwm.py # RGB → PWM calculator (used by ALM PWM assertions) │ ├── led_platform.py # Platform-specific LED helpers │ ├── Owon/ │ │ └── owon_psu_quick_demo.py # Standalone PSU demo │ ├── automated_lin_test/ # Reference scripts (test_animation.py etc.) │ │ ├── README.md │ │ ├── install_packages.sh # Installs Melexis pylin/pymumclient into the venv │ │ └── (test_*.py reference scripts) │ ├── BabyLIN_library.py # DEPRECATED official BabyLIN SDK Python wrapper │ ├── BLCInterfaceExample.py # DEPRECATED vendor example │ └── BabyLIN library/ # DEPRECATED platform binaries (DLL/.so) │ ├── reports/ # Generated per-run (HTML, JUnit, summary, coverage) │ ├── report.html │ ├── junit.xml │ ├── summary.md │ └── requirements_coverage.json │ ├── scripts/ │ ├── pi_install.sh # Raspberry Pi installer │ ├── ecu-tests.service # systemd unit │ ├── ecu-tests.timer # systemd timer │ ├── run_tests.sh # Convenience runner │ ├── run_two_reports.ps1 # Split unit/non-unit report runs (Windows) │ └── 99-babylin.rules # DEPRECATED udev rule │ ├── conftest_plugin.py # HTML metadata extraction + report customization ├── pytest.ini # Markers, addopts, junit_family=legacy ├── requirements.txt ├── README.md # ← you are here └── TESTING_FRAMEWORK_GUIDE.md # Deep dive companion to this README ``` For the hardware-test layer specifically, see [`docs/19_frame_io_and_alm_helpers.md`](docs/19_frame_io_and_alm_helpers.md) (FrameIO + AlmTester + the four-phase test pattern) and [`docs/14_power_supply.md`](docs/14_power_supply.md) §5 (session-managed PSU lifecycle). ## Usage recipes - Run everything (mock and any non-hardware tests): ```powershell python.exe -m pytest -v ``` - Run by marker: ```powershell python.exe -m pytest -m "smoke" -v python.exe -m pytest -m "req_001" -v ``` - Run in parallel: ```powershell python.exe -m pytest -n auto -v ``` - Run the plugin self-test (verifies reporting artifacts under `reports/`): ```powershell python -m pytest tests\plugin\test_conftest_plugin_artifacts.py -q ``` - Generate separate HTML/JUnit reports for unit vs non-unit tests: ```powershell ./scripts/run_two_reports.ps1 ``` ## BabyLIN adapter notes (DEPRECATED) > Kept for backward compatibility. New work should target the MUM adapter. The `ecu_framework/lin/babylin.py` implementation uses the official `BabyLIN_library.py` wrapper from the SDK. Put `BabyLIN_library.py` under `vendor/` (or on `PYTHONPATH`) along with the SDK's platform-specific libraries. Configure `sdf_path` and `schedule_nr` to load an SDF and start a schedule during connect. The adapter sends frames via `BLC_mon_set_xmit` and receives via `BLC_getNextFrameTimeout`. Instantiating `BabyLinInterface` emits a `DeprecationWarning`. ## Docs and references - Guide: `TESTING_FRAMEWORK_GUIDE.md` (deep dive with examples and step-by-step flows) - Reports: `reports/report.html` and `reports/junit.xml` (generated on each run) - CI summary: `reports/summary.md` (machine-friendly run summary) - Requirements coverage: `reports/requirements_coverage.json` (requirement → tests mapping) - Tip: Open the HTML report on Windows with: `start .\reports\report.html` - Configs: `config/test_config.yaml`, `config/mum.example.yaml`, `config/babylin.example.yaml` (deprecated) — copy and modify for your environment - BabyLIN SDK placement and notes: `vendor/README.md` (deprecated; only relevant for legacy BabyLIN rigs) - Docs index: `docs/README.md` (run sequence, config resolution, reporting, call flows) - Raspberry Pi deployment: `docs/09_raspberry_pi_deployment.md` - Build custom Pi image: `docs/10_build_custom_image.md` - Pi scripts: `scripts/pi_install.sh`, `scripts/ecu-tests.service`, `scripts/ecu-tests.timer`, `scripts/run_tests.sh` ## Troubleshooting - HTML report missing columns: ensure `pytest.ini` includes `-p conftest_plugin` in `addopts`. - ImportError for BabyLIN_library (DEPRECATED path): verify `vendor/BabyLIN_library.py` placement and that required native libraries (DLL/.so) from the SDK are available on PATH/LD_LIBRARY_PATH. Consider migrating to the MUM adapter, which avoids vendor DLLs entirely. - Permission errors in PowerShell: run the venv's full Python path or adjust ExecutionPolicy for scripts. - Import errors: activate the venv and reinstall `requirements.txt`. ## Owon Power Supply (SCPI) — library, config, tests, and quick demo We provide a reusable pyserial-based library, a hardware test integrated with the central config, and a minimal quick demo script. - Library: `ecu_framework/power/owon_psu.py` (class `OwonPSU`, `SerialParams`, `scan_ports`) - Central config: `config/test_config.yaml` (`power_supply` section) - Optionally merge `config/owon_psu.yaml` or set `OWON_PSU_CONFIG` to a YAML path - Hardware test: `tests/hardware/test_owon_psu.py` (skips unless `power_supply.enabled` is true) - quick demo: `vendor/Owon/owon_psu_quick_demo.py` (reads `OWON_PSU_CONFIG` or `config/owon_psu.yaml`) Quick setup (Windows PowerShell): ```powershell # Ensure dependencies pip install -r .\requirements.txt # Option A: configure centrally in test_config.yaml # Edit config\test_config.yaml and set: # power_supply.enabled: true # power_supply.port: COM4 # Option B: use a separate machine-specific YAML copy .\config\owon_psu.example.yaml .\config\owon_psu.yaml # edit COM port and options in .\config\owon_psu.yaml # Run the hardware PSU test (skips if disabled or missing port) pytest -k test_owon_psu_idn_and_optional_set -m hardware -q # Run the quick demo script python .\vendor\Owon\owon_psu_quick_demo.py ``` YAML keys supported by `power_supply`: ```yaml power_supply: enabled: true port: COM4 # or /dev/ttyUSB0 baudrate: 115200 timeout: 1.0 eol: "\n" # or "\r\n" 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 ``` Troubleshooting: - If `*IDN?` is empty, confirm port, parity/stopbits, and `eol` (try `\r\n`). - On Windows, if COM>9, use `\\.\COM10` style in some tools; here plain `COM10` usually works. - Ensure only one program opens the COM port at a time. ## Next steps - Replace `HexFlasher` with a production flashing routine (UDS) - Expand tests for end-to-end ECU workflows and requirement coverage