ecu-tests/docs/13_unit_testing_guide.md
Hosam-Eldin Mostafa 582764d410 Mark legacy BabyLIN adapter as deprecated across code and docs
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>
2026-05-07 17:32:24 +02:00

141 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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`
Youll 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`).