To install test dependencies, use:
uv sync --extra test
To run all tests, use:
uv run pytest
To run tests with coverage report:
uv run pytest --cov
To generate an HTML coverage report:
uv run pytest --cov=mpflash --cov-report=html
Open the generated htmlcov/index.html in your browser to view the coverage report.
The majority of thests is run using a (copy) of a populated database located in tests/data/mpflash.db
A number of fixtures have been setup in tests/conftest.py to simplify using the session or engine in tests. The fixtures are:
- session_fx: a session object that is used to run tests
- engine_fx: an engine object that is used to run tests
- db_fx: a database object that is used to run tests
The flash backends can also be exercised against real boards via the smoke tests in tests/hw/test_hw_backends.py. They are skipped by default and only run when both:
- The matching pytest marker is selected (each test is tagged with
hardwareplus one backend-specific marker). - The environment variables for that backend point at a connected board and a firmware file on disk.
| Marker | Backend | Required ports / probes |
|---|---|---|
hw_uf2 |
UF2 | RP2, SAMD or nRF board in bootloader (mass-storage) mode |
hw_dfu |
DFU | STM32 board in DFU mode |
hw_esptool |
esptool | ESP32 / ESP8266 board on a serial port |
hw_pyocd |
pyOCD | CMSIS-DAP / J-Link probe attached to a Cortex-M target |
All four tests also carry the umbrella hardware marker, so the default
suite (uv run pytest) excludes them. Run uv run pytest --markers to list
every marker.
Each backend is gated on two variables — one for the port/probe and one for the firmware file:
| Backend | Port variable | Firmware variable | Notes |
|---|---|---|---|
| UF2 | MPFLASH_HW_UF2_PORT |
MPFLASH_HW_UF2_FW |
Serial port or mounted UF2 volume |
| DFU | MPFLASH_HW_DFU_PORT |
MPFLASH_HW_DFU_FW |
.dfu or .bin file |
| esptool | MPFLASH_HW_ESP_PORT |
MPFLASH_HW_ESP_FW |
.bin file |
| pyOCD | MPFLASH_HW_PYOCD_PROBE |
MPFLASH_HW_PYOCD_FW |
Probe unique-id from pyocd list |
If a variable is unset or points at a missing file, the matching test is skipped with an explanatory message.
Install the test extras (and pyocd if you want to drive the pyOCD backend):
uv sync --extra test --extra pyocdUse one shared .env file for hardware settings (recommended):
# UF2 example
# Linux / WSL path examples:
MPFLASH_HW_UF2_PORT=/dev/ttyACM1
MPFLASH_HW_UF2_FW=/mnt/c/Users/jos_v/Downloads/firmware/rp2/RPI_PICO2-v1.28.0.uf2
# Native Windows path example (PowerShell / cmd):
# MPFLASH_HW_UF2_PORT=COM5
# MPFLASH_HW_UF2_FW=C:\Users\jos_v\Downloads\firmware\rp2\RPI_PICO2-v1.28.0.uf2
# Optional: tune loguru verbosity during pytest runs
LOGURU_LEVEL=INFOThis keeps board/probe and firmware paths in one place for:
- interactive debugging in VS Code
justrecipes- direct
uv run pytest ...command-line runs
Run a single backend from the command line (load .env first).
Linux / macOS / WSL:
set -a
source .env
set +a
uv run pytest -m hw_uf2 tests/hw -vWindows PowerShell:
Get-Content .env | ForEach-Object {
if ($_ -match '^\s*#' -or $_ -match '^\s*$') { return }
$name, $value = $_ -split '=', 2
[Environment]::SetEnvironmentVariable($name.Trim(), $value.Trim(), 'Process')
}
uv run pytest -m hw_uf2 tests/hw -vWith just, prefer enabling dotenv loading in justfile so recipes read .env
automatically:
set dotenv-load := trueThen run:
just hil_pico2This just command works on Linux/macOS/WSL and on Windows PowerShell
because set dotenv-load := true loads the same .env file before the recipe.
For interactive debugging in VS Code, point launch/test configuration at the
same .env file (for example envFile: ${workspaceFolder}/.env).
Run every hardware test for which the environment is configured:
uv run pytest -m hardware tests/hw -vWindows PowerShell uses the same pytest command once .env is loaded.
Combine markers to select a subset, e.g. UF2 + DFU only:
uv run pytest -m "hw_uf2 or hw_dfu" tests/hw -v- Serial ports:
mpflash list(orls /dev/serial/by-id/on Linux,pnputil /enum-devices /connectedon Windows). - pyOCD probes:
pyocd listprints each probe's unique-id copy that value intoMPFLASH_HW_PYOCD_PROBE.
Hardware tests should stay minimal — one happy-path call into
mpflash.flash.flash_mcu per backend. To add a new test:
- Mark it with
@pytest.mark.hw_<backend>(and rely on the module-levelpytestmark = pytest.mark.hardwarefor the umbrella marker). - Request the
hw_boardfixture plus the backend's firmware fixture (hw_uf2_firmware,hw_dfu_firmware, …) — both are defined in tests/hw/conftest.py. - Keep assertions to the externally observable result (an updated
MPRemoteBoard); leave deeper verification to the unit tests.