pytest-embedded-wireskein
A pytest-embedded plugin that gives each test a WireSkein recorder, ws_run. The test records the commands it sent, the logic-analyzer captures, and what each step should look like on the wire. When the test body ends, the plugin checks the captures against these expectations and fails the test if a check fails.
Status: beta.
Install
pip install pytest-embedded-wireskein
Python 3.11 or newer. This installs wireskein and pytest-embedded.
Use
from wireskein.runlog import square, level, only_moving
def test_pwm(dut, ws_run, probe): # `probe` is whatever drives your logic analyzer
with ws_run.section(1, "pwm"):
for duty in (64, 128, 0):
want = [square("PA1", 1000, duty / 255), only_moving(["PA1"])] if duty else [level("PA1", 0)]
with ws_run.section(2, f"duty={duty}", expect=want):
ws_run.command(f"PWM {duty}")
dut.write(f"PWM {duty}")
ws_run.reply(dut.expect(r"PWM duty=\d+").group(0).decode())
t = ws_run.armed() # time.monotonic() right after arming the capture
data, rate = probe.capture() # bytes, one sample per byte, bit k = pin k
ws_run.capture(t, rate, interleaved=data, names=["PA1", "PA0"])
When test_pwm returns, the plugin closes the run and verifies it. If a check fails, the test fails in its call phase (FAILED, not ERROR):
FAILED test_pwm.py::test_pwm - wireskein: 1 NG (5 ok, 1 ng, 0 unchecked (4 segments, 3 captures))
NG pwm/duty=128 square c0002.bin duty 0.6999 vs 0.5020
report: /tmp/pytest-embedded/2026-09-29_12-00-00-000000/test_pwm/wireskein/report.json
The checks (square, level, starts, ends, only_moving, pulses, i2c, spi, uart) and the heading rules are described in the WireSkein README.
Where the run is written
ws_run writes to <test_case_tempdir>/wireskein/, next to pytest-embedded's dut.log: <root-logdir>/pytest-embedded/<time>/<test name>/wireskein/.
| File | Content |
|---|---|
run.json |
Headings, commands, replies, notes, captures and expectations (WireSkein run format) |
c0001.wireskein, ... |
The captures, each channel at its own rate (wireskein info, wireskein convert c0001.wireskein c0001.sr for PulseView) |
report.json |
Every result with measured values, and the log |
report.xml |
The results as JUnit XML |
The same directory can be checked again later with wireskein verify <dir>. The test's user_properties carry wireskein_report (the path of report.json), and the result lines are added to the test report as a wireskein section (shown with -rA or on failure).
When the plugin verifies
- The run is verified after the test body, only if the test recorded a capture or an expectation.
- A check that fails makes the test fail.
- A check whose pins were not captured is unchecked and does not fail the test.
- If the test body already failed, the run is still recorded and verified, but the test's own failure is kept.
Options
| Option | ini | Default | Meaning |
|---|---|---|---|
--wireskein-verify=fail|report|off |
wireskein_verify |
fail |
fail: verify and fail on NG. report: verify and write the reports, never fail. off: record only |
--wireskein-unchecked=fail|pass |
wireskein_unchecked |
fail |
A check that could not be made (a pin not captured, no volt conversion, ...). fail: fails the test, since it is usually a mistake in the test or the wiring. pass: reported only. A check asked only to measure (uart(baud=None)) never fails |
ws_run is a wireskein.runlog.Recorder: its public methods (section, heading, command, reply, note, armed, capture, close, is_empty) are this plugin's API. The run format and the result statuses are in WireSkein's docs/run-format.ja.md.
Connecting a probe
This plugin knows nothing about probes or targets. A fixture that drives the logic analyzer (for example the one of a board-family plugin) connects to ws_run when both are installed:
- right after arming a capture:
t = ws_run.armed()(time.monotonic(); a capture client's own stamp of the same clock works too) - when the samples are read:
ws_run.capture(t, rate, interleaved=data, names=[...], width=8, positions=None, start_ns=..., start_uncertainty_ns=..., time_base_slipped=True).datais the probe's sample stream (widthbits per sample, channel k at bitpositions[k]),namesthe target's pin names in channel order. Passtime_base_slippedonly when the probe reports it. - channels at different rates:
ws_run.capture(t, tick_hz, channels=[wireskein.fileformat.Channel(name, bits, n, step=...)]) - anything else about the capture:
attachments={"probe.json": {...}} - the console traffic:
ws_run.command(text),ws_run.reply(text)
Development
uv sync
uv run pytest
Release
The release works the same way as in pytest-embedded-arduino-cli. Update ## Unreleased in CHANGELOG.md, then run the Release workflow with the version (for example 0.0.2). PyPI publishing uses Trusted Publishing.
License
MIT
Metadata
Release files for pytest-embedded-wireskein 0.0.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pytest_embedded_wireskein-0.0.4.tar.gz | 10.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pytest_embedded_wireskein-0.0.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 17.2 kB
Release files / pytest_embedded_wireskein-0.0.4.tar.gz
| Download URL | pytest_embedded_wireskein-0.0.4.tar.gz |
|---|---|
| Size | 10.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0492e84db58626c9b2b4a36e1c4f29634a26a87e5cdd9bebc39bcd158e7a1958
|
|
BLAKE2b-256 checksum How to use checksums |
431cef4f28cfb33babb09b366b7493e290e2aba7fbbc5ba3ab76fc3f672c09e9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency logRelease files / pytest_embedded_wireskein-0.0.4-py3-none-any.whl
| Download URL | pytest_embedded_wireskein-0.0.4-py3-none-any.whl |
|---|---|
| Size | 7.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
741d0d351fcb61cc323f285ed23074742850df59baa45efe90b2907f22fa3b29
|
|
BLAKE2b-256 checksum How to use checksums |
484cba2be1fff1446d889ef88c487d2154aa8273ae9a4e204bba8b7f5880c07d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.
Transparency log