West: Add west robot
command
Introduce `robot` command for running Robot Framework test suites. Initial implementation consists of one runner dedicated for renode-test, which is a Renode wrapper for running Robot tests. Signed-off-by: Michał Szprejda <mszprejda@antmicro.com>
This commit is contained in:
parent
80900cbc3b
commit
7c084b6649
12 changed files with 168 additions and 4 deletions
17
boards/common/renode_robot.board.cmake
Normal file
17
boards/common/renode_robot.board.cmake
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
board_set_robot_runner_ifnset(renode-robot)
|
||||||
|
|
||||||
|
# `--variable` is a renode-test argument, for setting a variable that can be later used in a .robot file:
|
||||||
|
# ELF: used in common.robot to set the `elf` variable in the default .resc script defined in board.cmake
|
||||||
|
# RESC: path to the .resc script, defined in board.cmake
|
||||||
|
# UART: default UART used by Robot in tests, defined in board.cmake
|
||||||
|
# KEYWORDS: path to common.robot, which contains common Robot keywords
|
||||||
|
# RESULTS_DIR: directory in which Robot artifacts will be generated after running a testsuite
|
||||||
|
board_runner_args(renode-robot "--renode-robot-arg=--variable=ELF:@${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}")
|
||||||
|
board_runner_args(renode-robot "--renode-robot-arg=--variable=RESC:@${RENODE_SCRIPT}")
|
||||||
|
board_runner_args(renode-robot "--renode-robot-arg=--variable=UART:${RENODE_UART}")
|
||||||
|
board_runner_args(renode-robot "--renode-robot-arg=--variable=KEYWORDS:${ZEPHYR_BASE}/tests/robot/common.robot")
|
||||||
|
board_runner_args(renode-robot "--renode-robot-arg=--variable=RESULTS_DIR:${APPLICATION_BINARY_DIR}")
|
||||||
|
|
||||||
|
board_finalize_runner_args(renode-robot)
|
|
@ -5,4 +5,6 @@ set(RENODE_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/support/m2gl025_miv.resc)
|
||||||
set(RENODE_UART sysbus.uart)
|
set(RENODE_UART sysbus.uart)
|
||||||
|
|
||||||
set_ifndef(BOARD_SIM_RUNNER renode)
|
set_ifndef(BOARD_SIM_RUNNER renode)
|
||||||
|
set_ifndef(BOARD_ROBOT_RUNNER renode-robot)
|
||||||
include(${ZEPHYR_BASE}/boards/common/renode.board.cmake)
|
include(${ZEPHYR_BASE}/boards/common/renode.board.cmake)
|
||||||
|
include(${ZEPHYR_BASE}/boards/common/renode_robot.board.cmake)
|
||||||
|
|
|
@ -30,4 +30,6 @@ elseif("${BOARD_REVISION}" STREQUAL "B")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_ifndef(BOARD_SIM_RUNNER renode)
|
set_ifndef(BOARD_SIM_RUNNER renode)
|
||||||
|
set_ifndef(BOARD_ROBOT_RUNNER renode-robot)
|
||||||
include(${ZEPHYR_BASE}/boards/common/renode.board.cmake)
|
include(${ZEPHYR_BASE}/boards/common/renode.board.cmake)
|
||||||
|
include(${ZEPHYR_BASE}/boards/common/renode_robot.board.cmake)
|
||||||
|
|
|
@ -101,6 +101,10 @@ function(create_runners_yaml)
|
||||||
runners_yaml_append("\n# Default simulation runner if --runner is not given.")
|
runners_yaml_append("\n# Default simulation runner if --runner is not given.")
|
||||||
runners_yaml_append("sim-runner: ${BOARD_SIM_RUNNER}")
|
runners_yaml_append("sim-runner: ${BOARD_SIM_RUNNER}")
|
||||||
endif()
|
endif()
|
||||||
|
if(DEFINED BOARD_ROBOT_RUNNER)
|
||||||
|
runners_yaml_append("\n# Default test runner if --runner is not given.")
|
||||||
|
runners_yaml_append("robot-runner: ${BOARD_ROBOT_RUNNER}")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Sets up common runner configuration values.
|
# Sets up common runner configuration values.
|
||||||
runners_yaml_append_config()
|
runners_yaml_append_config()
|
||||||
|
|
|
@ -705,7 +705,7 @@ endfunction()
|
||||||
# This section provides glue between CMake and the Python code that
|
# This section provides glue between CMake and the Python code that
|
||||||
# manages the runners.
|
# manages the runners.
|
||||||
|
|
||||||
set(TYPES "FLASH" "DEBUG" "SIM")
|
set(TYPES "FLASH" "DEBUG" "SIM" "ROBOT")
|
||||||
function(_board_check_runner_type type) # private helper
|
function(_board_check_runner_type type) # private helper
|
||||||
if (NOT "${type}" IN_LIST TYPES)
|
if (NOT "${type}" IN_LIST TYPES)
|
||||||
message(FATAL_ERROR "invalid type ${type}; should be one of: ${TYPES}")
|
message(FATAL_ERROR "invalid type ${type}; should be one of: ${TYPES}")
|
||||||
|
@ -724,7 +724,7 @@ endfunction()
|
||||||
#
|
#
|
||||||
# This would set the board's flash runner to "pyocd".
|
# This would set the board's flash runner to "pyocd".
|
||||||
#
|
#
|
||||||
# In general, "type" is FLASH, DEBUG or SIM and "runner" is
|
# In general, "type" is FLASH, DEBUG, SIM or ROBOT and "runner" is
|
||||||
# the name of a runner.
|
# the name of a runner.
|
||||||
function(board_set_runner type runner)
|
function(board_set_runner type runner)
|
||||||
_board_check_runner_type(${type})
|
_board_check_runner_type(${type})
|
||||||
|
@ -766,6 +766,11 @@ macro(board_set_debugger_ifnset runner)
|
||||||
board_set_runner_ifnset(DEBUG ${runner})
|
board_set_runner_ifnset(DEBUG ${runner})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
# A convenience macro for board_set_runner_ifnset(ROBOT ${runner}).
|
||||||
|
macro(board_set_robot_runner_ifnset runner)
|
||||||
|
board_set_runner_ifnset(ROBOT ${runner})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
# A convenience macro for board_set_runner_ifnset(SIM ${runner}).
|
# A convenience macro for board_set_runner_ifnset(SIM ${runner}).
|
||||||
macro(board_set_sim_runner_ifnset runner)
|
macro(board_set_sim_runner_ifnset runner)
|
||||||
board_set_runner_ifnset(SIM ${runner})
|
board_set_runner_ifnset(SIM ${runner})
|
||||||
|
|
|
@ -698,6 +698,44 @@ determined by the imported subclasses of ``ZephyrBinaryRunner``.
|
||||||
runner implementations are in other submodules, such as ``runners.nrfjprog``,
|
runner implementations are in other submodules, such as ``runners.nrfjprog``,
|
||||||
``runners.openocd``, etc.
|
``runners.openocd``, etc.
|
||||||
|
|
||||||
|
Running Robot Framework tests: ``west robot``
|
||||||
|
*********************************************
|
||||||
|
|
||||||
|
.. tip:: Run ``west robot -h`` for additional help.
|
||||||
|
|
||||||
|
Basics
|
||||||
|
======
|
||||||
|
|
||||||
|
Currently the command supports only one runner which is using ``renode-test``,
|
||||||
|
(essentially a wrapper for running Robot tests in Renode), but can be
|
||||||
|
easily extended by adding other runners.
|
||||||
|
|
||||||
|
From a Zephyr build directory, to run a Robot test suite::
|
||||||
|
|
||||||
|
west robot --runner=renode-robot --testsuite path/to/testsuite.robot
|
||||||
|
|
||||||
|
This will run all tests from testsuite.robot and print output provided
|
||||||
|
by Robot Framework.
|
||||||
|
|
||||||
|
To pass additional parameters to Renode use ``--renode-robot-args`` switch.
|
||||||
|
For example to show Renode logs in addition to Robot Framework's output:
|
||||||
|
|
||||||
|
west robot --runner=renode-robot --testsuite path/to/testsuite.robot --renode-robot-arg="--show-log"
|
||||||
|
|
||||||
|
Runner-Specific Overrides
|
||||||
|
=========================
|
||||||
|
|
||||||
|
To view all of the available options for the Robot runners your board
|
||||||
|
supports, as well as their usage information, use ``--context`` (or
|
||||||
|
``-H``)::
|
||||||
|
|
||||||
|
west robot --runner=renode-robot --context
|
||||||
|
|
||||||
|
|
||||||
|
To view all available options "renode-test" runner supports, use::
|
||||||
|
|
||||||
|
west robot --runner=renode-robot --renode-robot-help
|
||||||
|
|
||||||
Simulating a board with: ``west simulate``
|
Simulating a board with: ``west simulate``
|
||||||
******************************************
|
******************************************
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,11 @@ west-commands:
|
||||||
- name: bindesc
|
- name: bindesc
|
||||||
class: Bindesc
|
class: Bindesc
|
||||||
help: work with Binary Descriptors
|
help: work with Binary Descriptors
|
||||||
|
- file: scripts/west_commands/robot.py
|
||||||
|
commands:
|
||||||
|
- name: robot
|
||||||
|
class: Robot
|
||||||
|
help: run RobotFramework test suites
|
||||||
- file: scripts/west_commands/simulate.py
|
- file: scripts/west_commands/simulate.py
|
||||||
commands:
|
commands:
|
||||||
- name: simulate
|
- name: simulate
|
||||||
|
|
29
scripts/west_commands/robot.py
Normal file
29
scripts/west_commands/robot.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Copyright (c) 2024 Antmicro <www.antmicro.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
from west.commands import WestCommand
|
||||||
|
from run_common import add_parser_common, do_run_common
|
||||||
|
|
||||||
|
EXPORT_DESCRIPTION = '''\
|
||||||
|
Run RobotFramework test suites with a runner of choice.
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class Robot(WestCommand):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(Robot, self).__init__(
|
||||||
|
'robot',
|
||||||
|
# Keep this in sync with the string in west-commands.yml.
|
||||||
|
'run RobotFramework test suites',
|
||||||
|
EXPORT_DESCRIPTION,
|
||||||
|
accepts_unknown_args=True)
|
||||||
|
|
||||||
|
self.runner_key = 'robot-runner' # in runners.yaml
|
||||||
|
|
||||||
|
def do_add_parser(self, parser_adder):
|
||||||
|
return add_parser_common(self, parser_adder)
|
||||||
|
|
||||||
|
def do_run(self, my_args, runner_args):
|
||||||
|
do_run_common(self, my_args, runner_args)
|
|
@ -49,6 +49,7 @@ _names = [
|
||||||
'openocd',
|
'openocd',
|
||||||
'pyocd',
|
'pyocd',
|
||||||
'renode',
|
'renode',
|
||||||
|
'renode-robot',
|
||||||
'qemu',
|
'qemu',
|
||||||
'silabs_commander',
|
'silabs_commander',
|
||||||
'spi_burn',
|
'spi_burn',
|
||||||
|
|
|
@ -200,7 +200,7 @@ class MissingProgram(FileNotFoundError):
|
||||||
super().__init__(errno.ENOENT, os.strerror(errno.ENOENT), program)
|
super().__init__(errno.ENOENT, os.strerror(errno.ENOENT), program)
|
||||||
|
|
||||||
|
|
||||||
_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach', 'simulate'}
|
_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach', 'simulate', 'robot'}
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class RunnerCaps:
|
class RunnerCaps:
|
||||||
|
@ -212,7 +212,7 @@ class RunnerCaps:
|
||||||
Available capabilities:
|
Available capabilities:
|
||||||
|
|
||||||
- commands: set of supported commands; default is {'flash',
|
- commands: set of supported commands; default is {'flash',
|
||||||
'debug', 'debugserver', 'attach', 'simulate'}.
|
'debug', 'debugserver', 'attach', 'simulate', 'robot'}.
|
||||||
|
|
||||||
- dev_id: whether the runner supports device identifiers, in the form of an
|
- dev_id: whether the runner supports device identifiers, in the form of an
|
||||||
-i, --dev-id option. This is useful when the user has multiple debuggers
|
-i, --dev-id option. This is useful when the user has multiple debuggers
|
||||||
|
|
60
scripts/west_commands/runners/renode-robot.py
Normal file
60
scripts/west_commands/runners/renode-robot.py
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
# Copyright (c) 2024 Antmicro <www.antmicro.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
'''Runner stub for renode-test.'''
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
from runners.core import ZephyrBinaryRunner, RunnerCaps
|
||||||
|
|
||||||
|
|
||||||
|
class RenodeRobotRunner(ZephyrBinaryRunner):
|
||||||
|
'''Place-holder for Renode runner customizations.'''
|
||||||
|
|
||||||
|
def __init__(self, cfg, args):
|
||||||
|
super().__init__(cfg)
|
||||||
|
self.testsuite = args.testsuite
|
||||||
|
self.renode_robot_arg = args.renode_robot_arg
|
||||||
|
self.renode_robot_help = args.renode_robot_help
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def name(cls):
|
||||||
|
return 'renode-robot'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def capabilities(cls):
|
||||||
|
return RunnerCaps(commands={'robot'}, hide_load_files=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def do_add_parser(cls, parser):
|
||||||
|
parser.add_argument('--testsuite',
|
||||||
|
help='path to Robot test suite')
|
||||||
|
parser.add_argument('--renode-robot-arg',
|
||||||
|
metavar='ARG',
|
||||||
|
action='append',
|
||||||
|
help='additional argument passed to renode-test')
|
||||||
|
parser.add_argument('--renode-robot-help',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help='print all possible `renode-test` arguments')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def do_create(cls, cfg, args):
|
||||||
|
return RenodeRobotRunner(cfg, args)
|
||||||
|
|
||||||
|
def do_run(self, command, **kwargs):
|
||||||
|
self.run_test(**kwargs)
|
||||||
|
|
||||||
|
def run_test(self, **kwargs):
|
||||||
|
cmd = ['renode-test']
|
||||||
|
if self.renode_robot_help is True:
|
||||||
|
cmd.append('--help')
|
||||||
|
else:
|
||||||
|
if self.renode_robot_arg is not None:
|
||||||
|
for arg in self.renode_robot_arg:
|
||||||
|
cmd.append(arg)
|
||||||
|
if self.testsuite is not None:
|
||||||
|
cmd.append(self.testsuite)
|
||||||
|
else:
|
||||||
|
self.logger.error("No Robot testsuite passed to renode-test! Use the `--testsuite` argument to provide one.")
|
||||||
|
subprocess.run(cmd, check=True)
|
|
@ -40,6 +40,7 @@ def test_runner_imports():
|
||||||
'pyocd',
|
'pyocd',
|
||||||
'qemu',
|
'qemu',
|
||||||
'renode',
|
'renode',
|
||||||
|
'renode-robot',
|
||||||
'silabs_commander',
|
'silabs_commander',
|
||||||
'spi_burn',
|
'spi_burn',
|
||||||
'stm32cubeprogrammer',
|
'stm32cubeprogrammer',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue