ecu-tests/docs/01_run_sequence.md

4.8 KiB
Raw Blame History

Run Sequence: What Happens When You Start Tests

This document walks through the exact order of operations when you run the framework with pytest, what gets called, and where configuration/data is fetched from.

High-level flow

  1. You run pytest from PowerShell
  2. pytest reads pytest.ini and loads configured plugins (including our custom conftest_plugin)
  3. Test discovery collects tests under tests/
  4. Session fixtures run:
    • config() loads YAML configuration
    • lin() selects and connects the LIN interface (Mock or BabyLin)
    • flash_ecu() optionally flashes the ECU (if enabled)
  5. Tests execute using fixtures and call interface methods
  6. Our plugin extracts test metadata (Title, Requirements, Steps) from docstrings
  7. Reports are written to reports/report.html and reports/junit.xml

Detailed call sequence

sequenceDiagram
  autonumber
  participant U as User (PowerShell)
  participant P as pytest
  participant PI as pytest.ini
  participant PL as conftest_plugin.py
  participant T as Test Discovery (tests/*)
  participant F as Fixtures (conftest.py)
  participant C as Config Loader (ecu_framework/config.py)
  participant PS as Power Supply (optional)
  participant L as LIN Adapter (mock/BabyLIN SDK)
  participant X as HexFlasher (optional)
  participant R as Reports (HTML/JUnit)

  U->>P: python -m pytest [args]
  P->>PI: Read addopts, markers, plugins
  P->>PL: Load custom plugin hooks
  P->>T: Collect tests
  P->>F: Init session fixtures
  F->>C: load_config(workspace_root)
  C-->>F: EcuTestConfig (merged dataclasses)
  F->>L: Create interface (mock or BabyLIN SDK)
  L-->>F: Instance ready
  F->>L: connect()
  alt flash.enabled and hex_path provided
    F->>X: HexFlasher(lin).flash_hex(hex_path)
    X-->>F: Flash result (ok/fail)
  end
  opt power_supply.enabled and port provided
    Note over PS: Tests/tryouts may open PSU via ecu_framework.power.owon_psu
  end
  loop for each test
    P->>PL: runtest_makereport(item, call)
    Note over PL: Parse docstring and attach metadata
    P->>L: send()/receive()/request()
    L-->>P: Frames or None (timeout)
  end
  P->>R: Write HTML (with metadata columns)
  P->>R: Write JUnit XML
PowerShell → python -m pytest
  ↓
pytest loads pytest.ini
  - addopts: --junitxml, --html, --self-contained-html, -p conftest_plugin
  - markers registered
  ↓
pytest collects tests in tests/
  ↓
Session fixture: config()
  → calls ecu_framework.config.load_config(workspace_root)
    → determines config file path by precedence
    → merges YAML + overrides into dataclasses (EcuTestConfig)
    → optionally merges config/owon_psu.yaml (or OWON_PSU_CONFIG) into power_supply
  ↓
Session fixture: lin(config)
  → chooses interface by config.interface.type
    - mock → ecu_framework.lin.mock.MockBabyLinInterface(...)
  - babylin → ecu_framework.lin.babylin.BabyLinInterface(...)
  → lin.connect()
  ↓
Optional session fixture: flash_ecu(config, lin)
  → if config.flash.enabled and hex_path set
  → ecu_framework.flashing.HexFlasher(lin).flash_hex(hex_path)
  ↓
Test functions execute
  → use the lin fixture to send/receive/request
  ↓
Reporting plugin (conftest_plugin.py)
  → pytest_runtest_makereport parses test docstring
  → attaches user_properties: title, requirements, steps, expected_result
  → pytest-html hooks add Title and Requirements columns
  ↓
Reports written
  → reports/report.html (HTML with metadata columns)
  → reports/junit.xml (JUnit XML for CI)

Where information is fetched from

  • pytest configuration: pytest.ini
  • YAML config (default): config/test_config.yaml
  • YAML override via env var: ECU_TESTS_CONFIG
  • BabyLIN SDK wrapper and SDF path: interface.sdf_path and interface.schedule_nr in YAML
  • Test metadata: parsed from each tests docstring
  • Markers: declared in pytest.ini, attached in tests via @pytest.mark.*

Key components involved

  • tests/conftest.py: defines config, lin, and flash_ecu fixtures
  • ecu_framework/config.py: loads and merges configuration into dataclasses
  • ecu_framework/lin/base.py: abstract LIN interface contract and frame shape
  • ecu_framework/lin/mock.py: mock behavior for send/receive/request
  • ecu_framework/lin/babylin.py: BabyLIN SDK wrapper adapter (real hardware via BabyLIN_library.py)
  • ecu_framework/flashing/hex_flasher.py: placeholder flashing logic
  • conftest_plugin.py: report customization and metadata extraction

Edge cases and behavior

  • If interface.type is babylin but the SDK wrapper or libraries cannot be loaded, hardware tests are skipped
  • If flash.enabled is true but hex_path is missing, flashing fixture skips
  • Timeouts are honored in receive() and request() implementations
  • Invalid frame IDs (outside 0x000x3F) or data > 8 bytes will raise in LinFrame