125 lines
4.8 KiB
Markdown
125 lines
4.8 KiB
Markdown
# 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
|
||
|
||
```mermaid
|
||
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
|
||
```
|
||
|
||
```text
|
||
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 test’s 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 0x00–0x3F) or data > 8 bytes will raise in `LinFrame`
|