Additional Markers
pytest-embedded provides additional markers to enhance testing functionality.
skip_if_soc
The skip_if_soc marker allows you to skip tests based on the soc_caps (System-on-Chip capabilities) of a target device. These capabilities are defined in esp-idf. For example, for the ESP32, you can find them in the header file soc_caps.h.
Use Case
Imagine you have multiple targets, such as [esp32, esp32c3, ..., esp32s4], but you want to skip tests for chips that do not support specific features.
The skip_if_soc marker simplifies this by allowing you to define conditions based on the soc_caps property of your chip. This enables dynamic filtering of targets without requiring manual, target-specific logic.
Examples
Here are some examples of how to use skip_if_soc with different conditions:
Condition 1: A boolean expression like SOC_ULP_SUPPORTED != 1 and SOC_UART_NUM != 3. This skips tests for chips that:
Do not support the
low-power modefeature (SOC_ULP_SUPPORTED != 1).And have a UART number other than 3 (
SOC_UART_NUM != 3).
@pytest.mark.skip_if_soc("SOC_ULP_SUPPORTED != 1 and SOC_UART_NUM != 3")
@pytest.mark.parametrize("target", ["esp32", "esp32s2", "esp32c3"], indirect=True)
def test_template_first_condition():
pass
Condition 2: A boolean expression like SOC_ULP_SUPPORTED != 1 or SOC_UART_NUM != 3. This skips tests for chips that:
Either do not support the
low-power modefeature (SOC_ULP_SUPPORTED != 1).Or have a UART number other than 3 (
SOC_UART_NUM != 3).
@pytest.mark.skip_if_soc("SOC_ULP_SUPPORTED != 1 or SOC_UART_NUM != 3")
@pytest.mark.parametrize("target", ["esp32", "esp32s2", "esp32c3"], indirect=True)
def test_template_second_condition():
pass
Condition 3: You can use a shortcut to apply this condition to all ESP-IDF supported targets (assuming IDF_PATH is set).
import pytest
from esp_bool_parser.constants import SUPPORTED_TARGETS
@pytest.mark.skip_if_soc("SOC_ULP_SUPPORTED != 1")
@pytest.mark.parametrize("target", SUPPORTED_TARGETS, indirect=True)
def test_template():
pass
idf_parametrize
idf_parametrize is a wrapper around pytest.mark.parametrize that simplifies and extends string-based parameterization for tests. Using idf_parametrize makes testing parameters more flexible and easier to maintain.
Key Features:
Target Expansion: Automatically expands lists of supported targets, reducing redundancy in test definitions.
Markers: Use a marker as one of the parameters. If a marker is used, it should be the last parameter.
Use Cases
Target Extension
In scenarios where the supported targets are [esp32, esp32c3, esp32s3], idf_parametrize simplifies the process of creating parameterized tests by automatically expanding the target list.
By default, the values for SUPPORTED_TARGETS and PREVIEW_TARGETS are imported from:
from esp_bool_parser import PREVIEW_TARGETS, SUPPORTED_TARGETS
However, you can propagate custom values by using the following:
from pytest_embedded_idf.utils import supported_targets, preview_targets
supported_targets.set(CUSTOM_SUPPORT_TARGETS)
preview_targets.set(CUSTOM_SUPPORT_TARGETS)
Another way to override supported_targets and preview_targets is by using command-line arguments:
pytest --supported-targets esp32,esp32c3 --preview-targets esp32p4 ...
Example:
@idf_parametrize('target', [
('supported_targets'),
], indirect=True)
@idf_parametrize('config', [
'default',
'psram'
])
def test_st(dut: Dut) -> None:
...
Equivalent to:
@pytest.mark.parametrize('target', [
'esp32',
'esp32c3',
'esp32s3'
], indirect=True)
@pytest.mark.parametrize('config', [
'default',
'psram'
])
def test_st(dut: Dut) -> None:
...
Resulting Parameters Matrix:
Target |
Config |
|---|---|
esp32 |
default |
esp32c3 |
default |
esp32s3 |
default |
esp32 |
psram |
esp32c3 |
psram |
esp32s3 |
psram |
Markers
You can also pass markers as the last item in a parameter tuple. If a test case does not need extra markers, you can omit them.
Example:
In ESP-IDF testing, environment markers specify which test runner should execute the test. For example:
generic: Tests that run on standard test runners.
sdcard: Tests that require an SD card runner.
usb_device: Tests that require a USB device runner.
@pytest.mark.generic
@idf_parametrize('config', [
'defaults',
], indirect=['config'])
@idf_parametrize('target, markers', [
('esp32', (pytest.mark.usb_device,)),
('esp32c3',),
('esp32', (pytest.mark.sdcard,)),
], indirect=['target'])
def test_console(dut: Dut, config: str, target: str) -> None:
...
Resulting Parameters Matrix:
Target |
Config |
Markers |
|---|---|---|
esp32 |
defaults |
generic, usb_device |
esp32c3 |
defaults |
generic |
esp32 |
defaults |
generic, sdcard |
Examples
Target with Config
Example:
@idf_parametrize('target, config', [
('esp32', 'release'),
('esp32c3', 'default'),
('supported_targets', 'psram'),
], indirect=True)
def test_st(dut: Dut) -> None:
...
Resulting Parameters Matrix:
Target |
Config |
|---|---|
esp32 |
release |
esp32c3 |
default |
esp32 |
psram |
esp32c3 |
psram |
esp32s3 |
psram |
Supported Targets on Runners
Example:
@idf_parametrize('target, markers', [
('esp32', (pytest.mark.generic,)),
('esp32c3', (pytest.mark.sdcard,)),
('supported_targets', (pytest.mark.usb_device,)),
], indirect=True)
def test_st(dut: Dut) -> None:
...
Resulting Parameters Matrix:
Target |
Markers |
|---|---|
esp32 |
generic |
esp32c3 |
sdcard |
esp32 |
usb_device |
esp32c3 |
usb_device |
esp32s3 |
usb_device |
Runner for All Tests
Example:
@pytest.mark.generic
@idf_parametrize('target, config', [
('esp32', 'release'),
('esp32c3', 'default'),
('supported_targets', 'psram'),
], indirect=True)
def test_st(dut: Dut) -> None:
...
Resulting Parameters Matrix:
Target |
Config |
Markers |
|---|---|---|
esp32 |
release |
generic |
esp32c3 |
default |
generic |
esp32 |
psram |
generic |
esp32c3 |
psram |
generic |
esp32s3 |
psram |
generic |