chumicro-pytest-device
Pytest plugin that runs your tests in a CircuitPython or MicroPython runtime, on a real board or in a unix-port subprocess.
--target picks where a test runs. The default, device, intercepts collection under any functional_tests/ directory: it stages your library and test source onto the connected board via chumicro-deploy, executes the test in the device runtime, parses the result back, and passes or fails host-side pytest with the on-device outcome. device-unit puts a library's ordinary tests/ suite on the board instead, so the cross-runtime unit tests run against real firmware. unix-port runs that same suite in a MicroPython or CircuitPython unix-port subprocess, which gives you runtime-accurate results with no board plugged in. Device targets read devices.yml and follow the same workspace conventions as the rest of the ChuMicro tooling.
Part of the ChuMicro family: small, focused Python libraries for microcontrollers and laptops. Browse all workbench tools. This is a workbench tool: it runs on your laptop and drives the boards over serial.
Install
pip install chumicro-pytest-device
That brings both ChuMicro dependencies with it: chumicro-deploy (plus its pyserial / mpremote deps) and chumicro-workspace, along with msgpack and cryptography. The plugin auto-registers via the pytest11 entry point, so you don't need a pytest_plugins = [...] line in conftest.py. Native Windows isn't currently supported (the underlying chumicro-deploy raises WindowsNotSupportedError); WSL2 works.
Quick example
A functional test reads like a normal unit test. It just runs on the board:
# libraries/mylib/functional_tests/test_heartbeat.py
import time
from chumicro_timing import Heartbeat
from chumicro_timing.ticks import ticks_ms
def test_heartbeat_fires_on_real_clock() -> None:
heartbeat = Heartbeat(period_ms=10)
deadline = time.monotonic() + 1.0
fires = 0
while time.monotonic() < deadline:
if heartbeat.poll(ticks_ms()):
fires += 1
assert fires > 50
The libraries/<name>/functional_tests/ layout is what triggers the routing, so put the file there and the plugin takes over from pytest. Run it on every device your devices.yml defaults name:
pytest libraries/mylib/functional_tests --runtime both
The plugin discovers the board, stages libraries/mylib/src/ plus the test, executes on-device, parses the on-device pytest result back, and reports PASS or FAIL through host-side pytest.
With no board attached, the same library's ordinary unit tests run in a unix-port interpreter instead:
pytest libraries/mylib/tests --target unix-port --runtime micropython
What's included
Plugin modules
| Module | Purpose |
|---|---|
chumicro_pytest_device.plugin |
The pytest plugin entry-point module: collection interception, deploy orchestration, result reporting |
chumicro_pytest_device.runtime_config |
set_runtime_config(), called from a functional_tests/conftest.py, hands the device a config payload staged at /runtime_config.msgpack. Board-side code reads it through the usual chumicro_config.load_runtime_config() |
chumicro_pytest_device.features |
Per-board feature gating. A test file that declares __chumicro_features__ = ("esp32",) is dropped from the plan for any board that doesn't probe as carrying that feature |
chumicro_pytest_device.fixtures |
Host-side fixtures for networking tests: lan (LAN address, free port, wait-until-listening), mosquitto (spawns a broker), tcp_echo / udp_echo / tls_echo (echo servers, TLS with a generated self-signed cert), and host_driver (an HTTP client that fires once the board prints its ready marker) |
chumicro_pytest_device.testing |
Public fakes and builders for testing code that drives the plugin: FakeConfig, FakeSession, hot_path_device, prime_transport_cache, make_prepare_item, make_run_file_item, make_test_item |
chumicro_pytest_device.result_parser |
Parses on-device test output back into TestResult objects |
chumicro_pytest_device.pr_summary |
Renders a Markdown PR-summary block from captured run results; drop it into a CI step |
chumicro_pytest_device.backends |
The execution backends behind --target: the board transport and the unix-port subprocess |
Pytest options
| Option | Effect |
|---|---|
--target {device,device-unit,unix-port} |
Where tests run. device (the default) runs functional_tests/ on a board, device-unit runs libraries/<name>/tests/ on a board, unix-port runs that same suite in a unix-port subprocess |
--runtime {micropython,circuitpython,both} |
Override defaults.ide_runtime |
--micropython-device <id> |
Override defaults.micropython |
--circuitpython-device <id> |
Override defaults.circuitpython |
--micropython-binary <path> |
unix-port only: the MicroPython binary to spawn, ahead of .tools/micropython.path and PATH |
--circuitpython-binary <path> |
unix-port only: the CircuitPython binary to spawn, ahead of .tools/circuitpython.path and PATH |
--unix-port-timeout <seconds> |
unix-port only: per-file wall-clock ceiling; a worker that overruns is killed and the file fails cleanly |
--unix-port-heapsize <size> |
unix-port only: heap ceiling for workers (192K, say). Defaults to the per-runtime budgets in target-runtimes.toml; pass 0 or off for the port's native multi-MB heap |
--deploy-mode {ram,flash} |
Override the per-device deploy mode |
--per-file |
Device unit runs: soft-reset before each test file rather than once per library, so a big module starts on a fresh interpreter. Worth it on a 256 KB board |
--pr-summary |
Append a Markdown summary block to stdout at end of session |
--pr-summary-command <text> |
The command that re-runs the failed tests, included in the summary |
Where this fits
Two ChuMicro dependencies, both installed for you. chumicro-deploy is the transport that stages tests on a board. chumicro-workspace supplies the device-orchestration primitives the collection layer dispatches to (transport build, bootstrap runner, library-source walking) and is also what writes the devices.yml this plugin reads. Auto-registers via pytest11.
Companions
| Workbench tool | Why you'd use it alongside |
|---|---|
chumicro-deploy |
The transport layer the plugin uses for staging. Useful directly when you want to drive a board outside of pytest |
chumicro-repl |
Tail a board's REPL after a deploy, which is where you go next when a functional test surprises you |
chumicro-workspace |
The host CLI for project workspaces. Reads the same devices.yml schema |
Contributing
Issues, bug reports, and pull requests are welcome, and so is "I ran it on this board and here's what happened", some of the most useful feedback a hardware project can get. Development happens in the ChuMicro repository, whose contributing guide covers setup and the test workflow.
Find this library
- PyPI: chumicro-pytest-device
- Source: workbench/pytest-device
License
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chumicro_pytest_device-0.18.0.tar.gz.
File metadata
- Download URL: chumicro_pytest_device-0.18.0.tar.gz
- Upload date:
- Size: 63.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
41bebf1533d7e0f7176a8832831f3ddd5a24b2d7bb71801880791d61229ded97
|
|
| MD5 |
2e8268bd9f8241490cac39883ae73fa8
|
|
| BLAKE2b-256 |
568082d8193bdf7c46f68daa86e8cb1d4c7143a9afa30f91010a95cea26e2692
|
Provenance
The following attestation bundles were made for chumicro_pytest_device-0.18.0.tar.gz:
Publisher:
promote.yml on ChuMicro/ChuMicro
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chumicro_pytest_device-0.18.0.tar.gz -
Subject digest:
41bebf1533d7e0f7176a8832831f3ddd5a24b2d7bb71801880791d61229ded97 - Sigstore transparency entry: 2499704998
- Sigstore integration time:
-
Permalink:
ChuMicro/ChuMicro@9fe3aa25f1d3ad43e829d9061bd88df65d021806 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ChuMicro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
promote.yml@9fe3aa25f1d3ad43e829d9061bd88df65d021806 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file chumicro_pytest_device-0.18.0-py3-none-any.whl.
File metadata
- Download URL: chumicro_pytest_device-0.18.0-py3-none-any.whl
- Upload date:
- Size: 74.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f0437af6251c22b35c91b97dd3908a5ea384e5b4a3357149ff6852322e9748e
|
|
| MD5 |
95db2b49d76c05593ea5d0f4860fa177
|
|
| BLAKE2b-256 |
3eab1e9f2ac5f54c9388bf0fa4a6fc88de0360986d8cb00265d9947523b9dc82
|
Provenance
The following attestation bundles were made for chumicro_pytest_device-0.18.0-py3-none-any.whl:
Publisher:
promote.yml on ChuMicro/ChuMicro
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chumicro_pytest_device-0.18.0-py3-none-any.whl -
Subject digest:
3f0437af6251c22b35c91b97dd3908a5ea384e5b4a3357149ff6852322e9748e - Sigstore transparency entry: 2499705004
- Sigstore integration time:
-
Permalink:
ChuMicro/ChuMicro@9fe3aa25f1d3ad43e829d9061bd88df65d021806 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ChuMicro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
promote.yml@9fe3aa25f1d3ad43e829d9061bd88df65d021806 -
Trigger Event:
workflow_dispatch
-
Statement type: