Developer Guide¶
This guide explains how the framework is organized, how to extend it with new peripherals or CLI options, and what to keep in mind when contributing.
Code structure (high level)¶
src/py_micro_hil/cli.py— argument parsing and thehiltestsentrypoint.src/py_micro_hil/peripheral_config_loader.py— YAML parsing and device instantiation (real or dummy depending on platform).src/py_micro_hil/framework_API.py— getters that expose configured peripherals to tests.src/py_micro_hil/tests_group_factory.py— wraps modules into test groups, injects context, and handles setup/teardown.src/py_micro_hil/tests_framework.py— executes groups, aggregates results, and triggers report generation.src/py_micro_hil/logger.pyandreport_generator.py— console/file logging plus HTML report output.
Architecture and lifecycle¶
- The execution lifecycle and component responsibilities are detailed in the System Architecture & Extensibility Guide. Start there for a holistic view of how the CLI, loader, API, orchestrator, and reporter work together.
- Keep layers loosely coupled: tests interact only with the public API getters, not with concrete driver classes; the loader owns schema validation and instantiation logic; the CLI only prepares runtime context and dispatches.
Environment and setup for contributors¶
- Python 3.10+ with
pipandvenv. Install dev dependencies withpip install -e .[dev]. - Hardware runners (Raspberry Pi) need device permissions for GPIO, UART, SPI, and serial ports; host-only development can use dummy drivers.
- Recommended pre-commit checks:
ruff/flake8for style,pytestfor unit tests, andmypyorpyrightif you add typing-heavy code.
Adding new peripherals¶
- Implement a driver in
src/py_micro_hil/peripherals/that satisfies the pattern used byRPiGPIO,RPiPWM,RPiUART, etc. Provideinitialize()andrelease()plus any protocol-specific methods you need in tests. - Extend the YAML loader (
peripheral_config_loader.py) to parse a new block, validate defaults, and construct your driver. Emit clear warnings when user input is malformed. - Expose a getter in
framework_API.pyso test authors can retrieve the configured instance without importing your class directly. - Document the schema in
docs/hardware-configuration.mdand add a small usage example underdocs/writing-tests.md. - Add example tests under
example/hil_tests/(or a new folder) so users see end-to-end usage. - Verify dummy mode where possible so CI can exercise the feature without hardware access.
Extending the CLI¶
- The parser lives in
cli.py(parse_args()), and HTML path handling is inresolve_html_path(). - When adding options, update log messages and docs so users can discover the
feature via
--help. - Debug visibility is opt-in:
[DEBUG]messages are only emitted when the--debugflag is set and theLoggeris initialized withdebug_enabled=True. - Keep defaults ergonomic (e.g., sensible report locations, automatic folder creation) and log any inferred behavior so users understand what happened.
- Add regression tests for new flags to ensure interactions with defaults and report generation remain stable.
Reporting and logging internals¶
Loggercollects console, text log, and HTML entries. HTML output copies astyles.cssnext to the report file.- The test framework appends log entries as tests run; if generation fails, the CLI reports the error but does not block exit.
- Preserve report schemas (text + HTML) for backwards compatibility; introduce versioned fields if layouts change.
Testing expectations¶
- Add or update unit tests for loader changes, CLI flags, and report generation.
- For integration scenarios, prefer dummy drivers so tests remain portable.
- When touching timing-sensitive drivers, document and test expected tolerances to avoid regressions on slower CI hardware.
Contribution checklist¶
- Follow PEP 8; include or update unit tests where applicable.
- Run
pytestlocally when changing code paths. - Update documentation and examples when modifying the YAML schema, CLI flags, or report layout.
- Prefer incremental, well-scoped commits with descriptive messages.
- Include notes for release/version bumps when introducing breaking changes; add ADR entries for significant design decisions to keep architectural rationale discoverable.