Klab Pytest Toolkit - Embedded
Custom pytest fixtures for embedded systems testing. The goal is to allow testers to easily test embedded devices with reusable components for programming, resetting, and communicating with boards.
At the moment the package provides the following components:
Board: Main orchestration class for managing board operations, including programming, resetting, and communication.- Debug Probes:
EspTool: Debug probe implementation for ESP32 devices usingesptool.
- Communicators:
SerialCommunicator: Serial port communication interface for UART/USB connections.
Installation
pip install klab-pytest-toolkit-embedded
Usage
Board Class
The Board class orchestrates board operations by combining a debug probe (for programming and resetting) with a communicator (for sending and receiving data).
Create a fixture
import pytest
from pathlib import Path
from typing import Generator
from klab_pytest_toolkit_embedded.board import Board
from klab_pytest_toolkit_embedded.debug_probes import EspTool
from klab_pytest_toolkit_embedded.communicators import SerialCommunicator
@pytest.fixture
def dut() -> Generator[Board]:
"""Fixture to provide a Board instance for Device Under Test (DUT)."""
PORT = "/dev/ttyUSB0"
communicator = SerialCommunicator(port=PORT, baudrate=115200)
debug_probe = EspTool(port=PORT, baudrate=1500000, address="0x0")
with Board(debug_probe=debug_probe, communicator=communicator) as board:
yield board
Programming and Reset
def test_program_firmware(dut: Board):
"""Test programming firmware to the board."""
firmware_file = "path/to/firmware.bin"
dut.program(firmware_file)
# Firmware is now flashed to the device
def test_reset_board(dut: Board):
"""Test resetting the board."""
dut.reset()
# Board has been reset
Communication
The Board class provides methods for sending and receiving data:
def test_send_data(dut: Board):
"""Test sending data to the board."""
dut.send(b"Hello Device!\n")
def test_receive_data(dut: Board):
"""Test receiving data from the board."""
data = dut.receive_some(num_bytes=1024)
print(data.decode('utf-8', errors='ignore'))
def test_wait_for_boot_message(dut: Board):
"""Test waiting for a specific message during boot."""
firmware_file = "path/to/firmware.bin"
dut.program(firmware_file)
# Wait for boot message with regex
boot_message = b"Firmware Ready!"
assert dut.wait_for_regex_in_line(boot_message, timeout_s=10, log=True)
Serial Communicator
The SerialCommunicator provides serial communication functionality with configurable parameters:
from klab_pytest_toolkit_embedded.communicators import SerialCommunicator
# Create a serial communicator
communicator = SerialCommunicator(
port="/dev/ttyUSB0",
baudrate=115200,
timeout=1.0
)
# Send data
communicator.send(b"AT\r\n")
# Receive data
data = communicator.receive(num_bytes=100)
# Check available bytes
available = communicator.bytes_available()
# Flush buffers
communicator.flush_input()
communicator.flush_output()
# Close when done
communicator.close()
ESP Debug Probe
The EspTool class provides programming and reset functionality for ESP32 devices:
from klab_pytest_toolkit_embedded.debug_probes import EspTool
# Create ESP debug probe
esp_probe = EspTool(
port="/dev/ttyUSB0",
baudrate=1500000,
address="0x0"
)
# Program firmware
esp_probe.program("path/to/firmware.bin")
# Reset the device
esp_probe.reset()
# Close (no persistent connection for esptool)
esp_probe.close()
Examples
See the test files for comprehensive examples.
Best Practices
Use Context Managers
The Board class supports context managers to ensure proper cleanup of resources:
with Board(debug_probe=debug_probe, communicator=communicator) as board:
board.program(firmware_file)
board.wait_for_regex_in_line(b"Ready", timeout_s=10)
# Resources are automatically closed when exiting the context
Timeout Configuration
When waiting for messages from the device, always specify appropriate timeouts to prevent tests from hanging:
# Wait with custom timeout
dut.wait_for_regex_in_line(
regex=b"Boot complete",
timeout_s=30,
log=True # Enable logging to see device output
)
Hardware Availability
For tests that require physical hardware, use pytest.mark.skipif to conditionally skip tests when hardware is not available:
@pytest.mark.skipif(
not hardware_available(),
reason="This test requires a physical ESP32 device connected."
)
def test_with_hardware(dut: Board):
# Test code here
pass
Links
License
MIT
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 klab_pytest_toolkit_embedded-1.1.0.tar.gz.
File metadata
- Download URL: klab_pytest_toolkit_embedded-1.1.0.tar.gz
- Upload date:
- Size: 7.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
24bb17845310cd0b4bee0112a0f03072842a7acfd4763bbb18b095cc5e82efa1
|
|
| MD5 |
2dde4bf33fe564e963f53891b5c0e4f7
|
|
| BLAKE2b-256 |
a37a3e6bee6d6800208467ff0e272b21deb117b6e02b43d9025d1516546961aa
|
File details
Details for the file klab_pytest_toolkit_embedded-1.1.0-py3-none-any.whl.
File metadata
- Download URL: klab_pytest_toolkit_embedded-1.1.0-py3-none-any.whl
- Upload date:
- Size: 9.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1095016c7067b77f182ab6df01122c3a6b1c79b1083a3633bb69baf7ea2f4ace
|
|
| MD5 |
41094f408511d8e3a950a3729fbddd9b
|
|
| BLAKE2b-256 |
c4124c6919840c174336cca6746049ab6c12151e15857d9741b34c4d70c8f567
|