Skip to content

Commit bf2378e

Browse files
gchwierhenrikbrixandersen
authored andcommitted
twister: scripts: sharing of built applications
This feature enables sharing of built applications between test scenarios, allowing tests to access build artifacts from other applications. Signed-off-by: Grzegorz Chwierut <[email protected]>
1 parent 6cb06cd commit bf2378e

File tree

12 files changed

+354
-105
lines changed

12 files changed

+354
-105
lines changed

doc/develop/test/twister.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,43 @@ required_snippets: <list of needed snippets>
746746
- cdc-acm-console
747747
- user-snippet-example
748748
749+
required_applications: <list of required applications> (default empty)
750+
Specify a list of test applications that must be built before current test can run.
751+
It enables sharing of built applications between test scenarios, allowing tests
752+
to access build artifacts from other applications.
753+
754+
Each required application entry supports:
755+
- ``name``: Test scenario identifier (required)
756+
- ``platform``: Target platform (optional, defaults to current test's platform)
757+
758+
Required applications must be available in the source tree (specified with ``-T``
759+
and/or ``-s`` options). When reusing build directories (e.g., with ``--no-clean``),
760+
Twister can find required applications in the current build directory.
761+
762+
How it works:
763+
764+
- Twister builds the required applications first
765+
- The main test application waits for required applications to complete
766+
- Build directories of required applications are made available to the test harness
767+
- For pytest harness, build directories are passed via ``--required-build`` arguments
768+
and accessible through the ``required_build_dirs`` fixture
769+
770+
Example configuration:
771+
772+
.. code-block:: yaml
773+
774+
tests:
775+
sample.required_app_demo:
776+
harness: pytest
777+
required_applications:
778+
- name: sample.shared_app
779+
- name: sample.basic.helloworld
780+
platform: native_sim
781+
sample.shared_app:
782+
build_only: true
783+
784+
Limitations: Not supported with ``--subset`` or ``--runtime-artifact-cleanup`` options.
785+
749786
expect_reboot: <True|False> (default False)
750787
Notify twister that the test scenario is expected to reboot while executing.
751788
When enabled, twister will suppress warnings about unexpected multiple runs
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright (c) 2025 Nordic Semiconductor ASA
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
from __future__ import annotations
5+
6+
import logging
7+
from pathlib import Path
8+
9+
from twister_harness import DeviceAdapter
10+
11+
logger = logging.getLogger(__name__)
12+
13+
14+
def test_required_build_dirs_found(dut: DeviceAdapter, required_build_dirs):
15+
logger.info(f"Required build directories: {required_build_dirs}")
16+
assert len(required_build_dirs) == 2, "Expected two required build directories"
17+
assert Path(required_build_dirs[0]).is_dir()
18+
assert Path(Path(required_build_dirs[0]) / 'build.log').exists()

samples/subsys/testsuite/pytest/shell/testcase.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,11 @@ tests:
3333
- CONFIG_SHELL_VT100_COLORS=n
3434
harness_config:
3535
shell_commands: *kernel_commands
36+
sample.pytest.required_app_demo:
37+
required_applications:
38+
- name: sample.pytest.shell
39+
- name: sample.harness.shell
40+
harness: pytest
41+
harness_config:
42+
pytest_root:
43+
- "pytest_shared_app/test_shared_app.py"

scripts/pylib/pytest-twister-harness/src/twister_harness/fixtures.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ def shell(dut: DeviceAdapter) -> Shell:
8787
return shell
8888

8989

90+
@pytest.fixture(scope='session')
91+
def required_build_dirs(request: pytest.FixtureRequest) -> list[str]:
92+
return request.config.getoption('--required-build')
93+
94+
9095
@pytest.fixture()
9196
def mcumgr(device_object: DeviceAdapter) -> Generator[MCUmgr, None, None]:
9297
"""Fixture to create an MCUmgr instance for serial connection."""

scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ def pytest_addoption(parser: pytest.Parser):
126126
choices=('function', 'class', 'module', 'package', 'session'),
127127
help='The scope for which `dut` and `shell` fixtures are shared.'
128128
)
129+
twister_harness_group.addoption(
130+
'--required-build', action='append', default=[], metavar='PATH',
131+
help='Required build directory / shared applications for the test. '
132+
'May be given multiple times.'
133+
)
129134
twister_harness_group.addoption(
130135
'--twister-fixture', action='append', dest='fixtures', metavar='FIXTURE', default=[],
131136
help='Twister fixture supported by this platform. May be given multiple times.'

scripts/pylib/twister/twisterlib/config_parser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class TwisterConfigParser:
5555
"extra_conf_files": {"type": "list", "default": []},
5656
"extra_overlay_confs": {"type": "list", "default": []},
5757
"extra_dtc_overlay_files": {"type": "list", "default": []},
58+
"required_applications": {"type": "list"},
5859
"required_snippets": {"type": "list"},
5960
"build_only": {"type": "bool", "default": False},
6061
"build_on_all": {"type": "bool", "default": False},

scripts/pylib/twister/twisterlib/harness.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,9 @@ def generate_command(self):
435435
f'Support for handler {handler.type_str} not implemented yet'
436436
)
437437

438+
for req_build in self.instance.required_build_dirs:
439+
command.append(f'--required-build={req_build}')
440+
438441
if handler.type_str != 'device':
439442
for fixture in handler.options.fixture:
440443
command.append(f'--twister-fixture={fixture}')

0 commit comments

Comments
 (0)