The MUM (Melexis Universal Master) adapter is the current default; the
BabyLIN SDK adapter is retained only for backward compatibility with
existing rigs.
Code:
- Emit DeprecationWarning when BabyLinInterface is instantiated and
when tests/conftest.py routes interface.type=='babylin' to it.
- Update module/class docstrings in ecu_framework/{__init__,config,
lin/__init__,lin/babylin}.py to label BabyLIN-specific fields and
paths as deprecated.
Config / scripts / pytest:
- pytest.ini: relabel the babylin marker as deprecated.
- config/{babylin.example,examples,test_config}.yaml: add deprecation
banners and field comments.
- scripts/99-babylin.rules and scripts/pi_install.sh: annotate the
udev-rule install block as legacy-only.
Documentation:
- TESTING_FRAMEWORK_GUIDE.md, docs/08_babylin_internals.md, and
vendor/README.md: prepend explicit "DEPRECATED" banners.
- docs/{README,01,02,04,05,07,09,10,12,13,14,15,18,DEVELOPER_COMMIT_
GUIDE}.md: relabel "legacy" to "deprecated" where babylin is
mentioned, present MUM as the primary path, and steer new work
toward the MUM examples.
No tests, configs, or modules were deleted; existing BabyLIN setups
keep working but now produce a clear DeprecationWarning at runtime.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
141 lines
4.6 KiB
Markdown
141 lines
4.6 KiB
Markdown
# Unit Testing Guide
|
||
|
||
This guide explains how the project's unit tests are organized, how to run them (with and without markers), how coverage is generated, and tips for writing effective tests.
|
||
|
||
## Why unit tests?
|
||
|
||
- Fast feedback without hardware
|
||
- Validate contracts (config loader, frames, adapters, flashing scaffold)
|
||
- Keep behavior stable as the framework evolves
|
||
|
||
## Test layout
|
||
|
||
- `tests/unit/` — pure unit tests (no hardware, no external I/O)
|
||
- `test_config_loader.py` — config precedence and defaults
|
||
- `test_linframe.py` — `LinFrame` validation
|
||
- `test_babylin_adapter_mocked.py` — DEPRECATED BabyLIN adapter error paths with a mocked SDK wrapper
|
||
- `test_mum_adapter_mocked.py` — MUM adapter (`MumLinInterface`) plumbing exercised through fake `pylin` / `pymumclient` modules
|
||
- `test_hex_flasher.py` — flashing scaffold against a stub LIN interface
|
||
- `tests/plugin/` — plugin self-tests using `pytester`
|
||
- `test_conftest_plugin_artifacts.py` — verifies JSON coverage and summary artifacts
|
||
- `tests/` — existing smoke/mock/hardware tests
|
||
|
||
## Markers and selection
|
||
|
||
A `unit` marker is provided for easy selection:
|
||
|
||
- By marker (recommended):
|
||
|
||
```powershell
|
||
pytest -m unit -q
|
||
```
|
||
|
||
- By path:
|
||
|
||
```powershell
|
||
pytest tests\unit -q
|
||
```
|
||
|
||
- Exclude hardware:
|
||
|
||
```powershell
|
||
pytest -m "not hardware" -v
|
||
```
|
||
|
||
## Coverage
|
||
|
||
Coverage is enabled by default via `pytest.ini` addopts:
|
||
|
||
- `--cov=ecu_framework --cov-report=term-missing`
|
||
|
||
You’ll see a summary with missing lines directly in the terminal. To disable coverage locally, override addopts on the command line:
|
||
|
||
```powershell
|
||
pytest -q -o addopts=""
|
||
```
|
||
|
||
(Optional) To produce an HTML coverage report, you can add `--cov-report=html` and open `htmlcov/index.html`.
|
||
|
||
## Writing unit tests
|
||
|
||
- Prefer small, focused tests
|
||
- For the **deprecated** BabyLIN adapter logic, inject `wrapper_module` with the mock (kept for legacy coverage; new tests should target MUM):
|
||
|
||
```python
|
||
from ecu_framework.lin.babylin import BabyLinInterface # DeprecationWarning on use
|
||
from vendor import mock_babylin_wrapper as mock_bl
|
||
|
||
lin = BabyLinInterface(wrapper_module=mock_bl)
|
||
lin.connect()
|
||
# exercise send/receive/request
|
||
```
|
||
|
||
- For MUM adapter logic, inject `mum_module` and `pylin_module` with fakes
|
||
(see `tests/unit/test_mum_adapter_mocked.py` for a full example):
|
||
|
||
```python
|
||
from ecu_framework.lin.mum import MumLinInterface
|
||
|
||
# fake_mum exposes MelexisUniversalMaster() returning an object with
|
||
# open_all(host) and get_device(name)
|
||
# fake_pylin exposes LinBusManager(linmaster) and LinDevice22(lin_bus)
|
||
lin = MumLinInterface(host="10.0.0.1", mum_module=fake_mum, pylin_module=fake_pylin)
|
||
lin.connect()
|
||
# exercise send / receive / send_raw / power_*
|
||
```
|
||
|
||
- To simulate specific (deprecated) SDK signatures, use a thin shim (see `_MockBytesOnly` in `tests/test_babylin_wrapper_mock.py`).
|
||
- Include a docstring with Title/Description/Requirements/Steps/Expected Result so the reporting plugin can extract metadata (this also helps the HTML report).
|
||
- When testing the plugin itself, use the `pytester` fixture to generate a temporary test run and validate artifacts exist and contain expected entries.
|
||
|
||
## Typical commands (Windows PowerShell)
|
||
|
||
- Run unit tests with coverage:
|
||
|
||
```powershell
|
||
pytest -m unit -q
|
||
```
|
||
|
||
- Run only plugin self-tests:
|
||
|
||
```powershell
|
||
pytest tests\plugin -q
|
||
```
|
||
|
||
- Run the specific plugin artifact test (verifies HTML/JUnit, summary, and coverage JSON under `reports/`):
|
||
|
||
```powershell
|
||
python -m pytest tests\plugin\test_conftest_plugin_artifacts.py -q
|
||
```
|
||
|
||
- Run all non-hardware tests with verbose output:
|
||
|
||
```powershell
|
||
pytest -m "not hardware" -v
|
||
```
|
||
|
||
- Open the HTML report:
|
||
|
||
```powershell
|
||
start .\reports\report.html
|
||
```
|
||
|
||
- Generate two separate reports (unit vs non-unit):
|
||
|
||
```powershell
|
||
./scripts/run_two_reports.ps1
|
||
```
|
||
|
||
## CI suggestions
|
||
|
||
- Run `-m unit` and `tests/plugin` on every PR
|
||
- Optionally run mock integration/smoke on PR
|
||
- Run hardware test matrix on a nightly or on-demand basis (`-m "hardware and mum"`; `-m "hardware and babylin"` is deprecated and only for legacy rigs)
|
||
- Publish artifacts from `reports/`: HTML/JUnit/coverage JSON/summary MD
|
||
|
||
## Troubleshooting
|
||
|
||
- Coverage not showing: ensure `pytest-cov` is installed (see `requirements.txt`) and `pytest.ini` addopts include `--cov`.
|
||
- Import errors: activate the venv and reinstall requirements.
|
||
- Plugin artifacts missing under `pytester`: verify tests write to `reports/` (our plugin creates the folder automatically in `pytest_configure`).
|