Services

Fixtures

Please refer to instructions under the “fixtures defined from pytest_embedded.plugin” chapter of the output of pytest --fixtures.

CLI Options

Please refer to the instructions under the “embedded” or “embedded-[SERVICE]” groups of the output of pytest --help.

Dependency Graph for Services

The arrow points from the dependent service to the service it depends on. For example, pytest-embedded-serial-esp depends on pytest-embedded-serial.

        graph LR
    pytest-embedded-serial

    pytest-embedded-nuttx --> pytest-embedded-serial
    pytest-embedded-nuttx -->|optional, support test on espressif chips| pytest-embedded-serial-esp
    pytest-embedded-nuttx -->|optional, support test on qemu| pytest-embedded-qemu

    pytest-embedded-serial-esp --> pytest-embedded-serial

    pytest-embedded-jtag --> pytest-embedded-serial

    pytest-embedded-idf -->|optional, support test on espressif chips| pytest-embedded-serial-esp
    pytest-embedded-idf -->|optional, support test on qemu| pytest-embedded-qemu
    pytest-embedded-idf -->|optional, support test on esp-emu| pytest-embedded-espemu
    pytest-embedded-idf -->|optional, support test on wokwi| pytest-embedded-wokwi

    pytest-embedded-arduino -->|optional, support test on espressif chips| pytest-embedded-serial-esp
    pytest-embedded-arduino -->|optional, support test on qemu| pytest-embedded-qemu
    pytest-embedded-arduino -->|optional, support test on wokwi| pytest-embedded-wokwi
    

Supported Services

Activate a service would enable a set of fixtures or add some extra functionalities to a few fixtures.

pytest-embedded-serial

A pytest-embedded service for interacting with target hardware over serial (UART) ports.

Service Activation

Activate this service by passing serial to --embedded-services:

pytest --embedded-services serial --port /dev/ttyUSB0

Extra Functionalities

  • serial Fixture: Provides a Serial object that manages port connection, reading, and writing.

  • dut Integration: Automatically streams all incoming serial output to the dut and pexpect_proc fixtures for pattern matching.

  • Port Matching: Select serial ports by device path or USB bus location.

CLI Options

  • --port: Path to the serial port (e.g. /dev/ttyUSB0, COM3). Default: None.

  • --port-location: USB device location string (format: <bus>-<port>[-<port>]...) to match dynamic port paths.

  • --baud: Serial communication baud rate. Default: 115200.

Quick Example

from pytest_embedded import Dut


def test_serial_echo(dut: Dut):
    dut.write(b'ping\r\n')
    dut.expect('pong')

pytest-embedded-serial-esp

A pytest-embedded service that extends pytest-embedded-serial with esptool integration for Espressif SoCs (ESP32 series).

Service Activation

Activate this service by passing esp to --embedded-services:

pytest --embedded-services esp --app-path /path/to/app

Extra Functionalities

  • Automatic Chip & Port Detection: Uses esptool to query the connected chip and automatically detect the chip model (e.g. esp32, esp32c3, esp32s3) and available serial ports.

  • Device Filtering: Disambiguate multiple connected development boards by MAC address or USB serial number.

  • Flashing Controls: Configure flashing baud rate, force mode, full flash erasure, or separate flash and monitor ports.

CLI Options

  • --target: Expected target chip type. Default: "auto".

  • --beta-target: Beta version target chip type. Default: same as --target.

  • --flash-port: Dedicated serial port for flashing when separate from the monitoring port. Default: None.

  • --port-mac: Expected MAC address of the target board. Default: None.

  • --port-serial-number: Comma-separated list of USB serial numbers to filter available ports. Default: None.

  • --esptool-baud: Baud rate used during flashing. Default: 921600 (or ESPBAUD environment variable).

  • --skip-autoflash: Skip automatically flashing the binary to target flash. Default: False.

  • --erase-all: Erase the entire flash chip before writing binaries. Default: False.

  • --esp-flash-force: Force flashing mode in esptool. Default: False.

  • --add-target-as-marker-with-amount: Attach target chip as a test marker. Default: False.

Quick Example

from pytest_embedded import Dut


def test_chip_info(dut: Dut):
    print(f'Connected to target chip: {dut.app.target}')
    dut.expect('Hello world!')

pytest-embedded-idf

A pytest-embedded service tailored for ESP-IDF applications and test workflows.

Service Activation

Activate this service by passing idf to --embedded-services. Typically used together with esp for physical hardware testing:

pytest --embedded-services esp,idf --app-path /path/to/esp-idf-app

Extra Functionalities

  • App Metadata Parsing: Reads project_description.json and build artifacts to identify the target chip, flash settings, partition tables, and binary paths.

  • Smart Flashing & Caching: Automatically flashes the bootloader, partition table, and application. Caches binary hashes across the session to skip redundant flashing.

  • Panic & Core Dump Decoding: Automatically parses and decodes panic stack traces and core dumps from target flash/UART when a test fails.

  • Partition Table & NVS Controls: Erase NVS blocks or customize the partition tool script.

  • Unity Test Runner: Integrated support for Unity C test suites via dut.expect_unity_test_output() and the case_tester fixture for test menu navigation.

  • Linux Target Support: Includes LinuxDut and LinuxSerial to test ESP-IDF POSIX/Linux applications directly on the host machine.

  • Dynamic Parametrization: Provides idf_parametrize to expand supported_targets and filter chips by SoC capability strings.

CLI Options

  • --supported-targets: Comma-separated list of officially supported targets for the test. Default: None.

  • --preview-targets: Comma-separated list of preview/experimental targets for the test. Default: None.

  • --part-tool: Path to the partition table generator script. Default: $IDF_PATH/components/partition_table/gen_esp32part.py.

  • --confirm-target-elf-sha256: Verify ELF SHA256 against target flash before skipping re-flashing. Default: False.

  • --erase-nvs: Erase NVS partition blocks when flashing binaries. Default: False.

  • --skip-check-coredump: Skip auto-checking for core dumps and panic traces on test failure. Default: False.

Quick Example

from pytest_embedded import Dut


def test_idf_app(dut: Dut):
    # App information is parsed automatically from the ESP-IDF build directory
    print(f'Running target: {dut.app.target}')
    dut.expect('Booting ESP-IDF app...')
    dut.expect('Hello world!')

pytest-embedded-jtag

A pytest-embedded service for hardware debugging via OpenOCD and GDB.

Service Activation

Activate this service by passing jtag to --embedded-services:

pytest --embedded-services serial,jtag --app-path /path/to/app

Extra Functionalities

  • openocd Fixture: Launches and manages an OpenOCD background process. Supports sending commands over the OpenOCD Telnet port.

  • gdb Fixture: Launches and manages a GDB process connected to the target debugger.

  • Output Duplication: Duplicates both OpenOCD and GDB output streams into dut.pexpect_proc for unified log matching.

CLI Options

  • --openocd-prog-path: Path to the OpenOCD executable. Default: "openocd".

  • --openocd-cli-args: Arguments passed to OpenOCD. Default: "-f board/esp32-wrover-kit-3.3v.cfg".

  • --gdb-prog-path: Path to the architecture-specific GDB executable. Default: "xtensa-esp32-elf-gdb".

  • --gdb-cli-args: Arguments passed to GDB. Default: "--quiet".

  • --no-gdb: Set to True to skip creating the GDB instance when only OpenOCD is needed. Default: False.

Quick Example

from pytest_embedded import Dut
from pytest_embedded_jtag import Gdb, OpenOcd


def test_jtag_debugging(dut: Dut, openocd: OpenOcd, gdb: Gdb):
    gdb.write('target remote :3333')
    gdb.expect('Remote debugging using :3333')
    gdb.write('monitor reset halt')
    dut.expect('Target halted')

pytest-embedded-qemu

A pytest-embedded service for executing test cases in a QEMU virtual machine without physical hardware.

Service Activation

Activate this service by passing qemu to --embedded-services. Typically paired with idf:

pytest --embedded-services idf,qemu --app-path /path/to/app

Extra Functionalities

  • Automatic Image Generation: When used with idf, automatically merges binaries (bootloader, partition table, and app) into a single bootable QEMU flash image.

  • qemu Fixture: Launches and supervises the QEMU process.

  • Flash Encryption Simulation: Supports pre-encrypted flash images using a specified key file.

  • eFuse Support: Allows specifying virtual eFuse states for chip feature simulation.

CLI Options

  • --qemu-image-path: Path to the QEMU flash image binary. Default: <app_path>/flash_image.bin.

  • --qemu-prog-path: Path to the QEMU executable. Default: "qemu-system-xtensa".

  • --qemu-cli-args: Base CLI options for QEMU. Default: "-nographic -machine esp32".

  • --qemu-extra-args: Extra arguments appended to the QEMU command line. Default: None.

  • --qemu-efuse-path: Path to an eFuse file to simulate burn-in values. Default: None.

  • --skip-regenerate-image: Skip recreating the flash image if one is already present. Default: False.

  • --encrypt: Enable pre-encryption flash simulation workflow. Default: False.

  • --keyfile: Path to the encryption key file for the pre-encrypted workflow. Default: None.

Quick Example

from pytest_embedded import Dut


def test_qemu_execution(dut: Dut):
    # Runs entirely in QEMU software emulation
    dut.expect('Booting ESP-IDF app...')
    dut.expect('Hello world!')

pytest-embedded-espemu

A pytest-embedded service for running tests on esp-emu, Espressif’s lightweight emulator for ESP RISC-V series SoCs, without real hardware.

Supported targets: esp32c3, esp32c6, esp32h2, esp32p4, esp32s31.

Service Activation

Activate this service by passing espemu to --embedded-services. Typically combined with idf:

pytest --embedded-services idf,espemu --target esp32c3 --app-path /path/to/app

Extra Functionalities

  • Automatic Merged Binary: Automatically generates a merged flash binary from the build artifacts using esptool merge-bin.

  • Unity Test Support: Fully supports Unity test menus and automated test cases from pytest-embedded-idf.

  • Fast Execution: Lightweight software emulation running UART0 directly on standard I/O.

CLI Options

  • --espemu-image-path: Path to an existing merged flash binary instead of generating one. Default: <app_path>/<build_dir>/espemu_image.bin.

  • --espemu-prog-path: Path to the esp-emu executable. Default: "esp-emu".

  • --espemu-cli-args: Base arguments passed to esp-emu. Default: None.

  • --espemu-extra-args: Extra arguments appended to the esp-emu command line (e.g. --espemu-extra-args "--net user,restrict=yes"). Default: None.

Quick Example

from pytest_embedded import Dut


def test_espemu(dut: Dut):
    dut.expect('Hello from esp-emu!')

pytest-embedded-arduino

A pytest-embedded service for testing Arduino sketch builds on embedded targets.

Service Activation

Activate this service by passing arduino to --embedded-services. Typically combined with esp to enable flashing and serial monitoring:

pytest --embedded-services esp,arduino --app-path /path/to/arduino-build

Extra Functionalities

  • Sketch Metadata Parsing: Automatically locates the compiled sketch binary, bootloader, and partition table from the Arduino build folder.

  • Fast Flashing: Uses differential flashing (--diff-with) to only write updated flash sectors, significantly speeding up consecutive test runs.

  • Full Reflash Option: Easily disable fast flashing with --no-fast-flash when the flash state is unknown (such as after OTA tests).

CLI Options

  • --no-fast-flash: Disable fast differential flashing and write the complete flash image. Default: False.

Quick Example

from pytest_embedded import Dut


def test_arduino_sketch(dut: Dut):
    dut.expect('Setup complete')
    dut.expect('Sensor read: ')

pytest-embedded-wokwi

pytest-embedded service for running tests on Wokwi instead of the real target.

Wokwi supports most ESP32 targets, including: esp32, esp32s2, esp32s3, esp32c3, esp32c6, and esp32h2. In addition, it supports a wide range of peripherals, including sensors, displays, motors, and debugging tools.

Running the tests with Wokwi requires an internet connection. Your firmware is uploaded to the Wokwi server for the duration of the simulation, but it is not saved on the server. On-premises Wokwi installations are available for enterprise customers.

Wokwi API Tokens

Before using this plugin, you need to create a free Wokwi account and generate an API key. You can then set the WOKWI_CLI_TOKEN environment variable to the API key.

Linux / Mac OS / WSL:

export WOKWI_CLI_TOKEN="your-api-key"

Windows PowerShell:

$env:WOKWI_CLI_TOKEN="your-api-key"

Usage

To run your tests with Wokwi, make sure to specify the wokwi service when running pytest, e.g.:

pytest --embedded-services idf,wokwi

USB Serial JTAG

By default, Wokwi diagrams use UART connections ($serialMonitor:TX/$serialMonitor:RX) for serial communication. Some targets (e.g. ESP32-P4) can use USB Serial JTAG instead. You can enable this with the --wokwi-usb-serial-jtag flag:

pytest --embedded-services idf,wokwi --wokwi-usb-serial-jtag true

This works for both auto-generated diagrams and diagrams loaded from disk (including those specified via --wokwi-diagram). When enabled, the flag will:

  • Set the serialInterface attribute to USB_SERIAL_JTAG on the board part

  • Remove any $serialMonitor connections from the diagram

Writing Tests

When writing tests for your firmware, you can use the same pytest fixtures and assertions as you would for local testing. The main difference is that your tests will be executed in the Wokwi simulation environment and you have access to the Wokwi API for controlling the simulation through the wokwi fixture.

All interactions with the Wokwi simulation is through the wokwi.client - wokwi-python-client

For example, you can use wokwi.client.set_control() to control virtual components in the simulation, such as buttons, LEDs, and other peripherals. Whole documentations can be found at Wokwi Documentation

Quick Example: Button Test

import logging
from pytest_embedded import Dut
from pytest_embedded_wokwi import Wokwi


def test_gpio(dut: Dut, wokwi: Wokwi):
    logger = logging.getLogger(__name__)

    logger.info('Waiting for Button test begin...')
    dut.expect_exact('Button test')

    for i in range(3):
        logger.info(f'Setting button pressed for {i + 1} seconds')
        wokwi.client.set_control('btn1', 'pressed', 1)

        dut.expect_exact(f'Button pressed {i + 1} times')
        wokwi.client.set_control('btn1', 'pressed', 0)

pytest-embedded-nuttx

A pytest-embedded service for testing Apache NuttX RTOS firmware on physical targets or in QEMU.

Service Activation

Activate this service by passing nuttx to --embedded-services. Combine with serial (and optionally esp for Espressif chips):

pytest --embedded-services serial,esp,nuttx --app-path /path/to/nuttx/build

Or run NuttX tests inside QEMU:

pytest --embedded-services qemu,nuttx --app-path /path/to/nuttx/build

Extra Functionalities

  • NuttX App Detection: Scans the NuttX build directory for bootloader, partition table, and firmware ELF/binary files.

  • NuttShell (NSH) Interaction: Seamlessly runs commands in NuttShell via the serial port and verifies command exit codes.

  • Flashing & Reset Support: Leverages the esp service to automatically flash Espressif chips and trigger hardware resets.

  • Emulation Support: Supports running NuttX binaries inside the QEMU emulator.

Quick Example

from pytest_embedded import Dut


def test_nuttx_shell(dut: Dut):
    # Wait for the NuttShell prompt
    dut.expect('nsh>')
    dut.write('help\n')
    dut.expect('Builtin Apps:')