Movatterモバイル変換


[0]ホーム

URL:


Robot Framework User Guide

Version 7.3.2

Copyright © 2008-2015 Nokia Networks
Copyright © 2016- Robot Framework Foundation
Licensed under theCreative Commons Attribution 3.0 Unported license

Table of Contents

1   Getting started

1.1   Introduction

Robot Framework is a Python-based, extensible keyword-driven automationframework for acceptance testing, acceptance test driven development (ATDD),behavior driven development (BDD) and robotic process automation (RPA). Itcan be used in distributed, heterogeneous environments, where automationrequires using different technologies and interfaces.

The framework has a rich ecosystem around it consisting of various genericlibraries and tools that are developed as separate projects. For moreinformation about Robot Framework and the ecosystem, seehttp://robotframework.org.

Robot Framework is open source software released under theApache License2.0. Its development is sponsored by theRobot Framework Foundation.

Note

The official RPA support was added in Robot Framework 3.1.This User Guide still talks mainly about creating tests, test data,and test libraries, but same concepts apply also whencreatingtasks.

1.1.1   Why Robot Framework?

  • Enables easy-to-use tabular syntax forcreating test cases in a uniformway.
  • Provides ability to create reusablehigher-level keywords from theexisting keywords.
  • Provides easy-to-read resultreports andlogs in HTML format.
  • Is platform and application independent.
  • Provides a simplelibrary API for creating customized test librarieswhich can be implemented natively with Python.
  • Provides acommand line interface and XML basedoutput files forintegration into existing build infrastructure (continuous integrationsystems).
  • Provides support for testing web applications, rest APIs, mobile applications,running processes, connecting to remote systems via Telnet or SSH, and so on.
  • Supports creatingdata-driven test cases.
  • Has built-in support forvariables, practical particularly for testing indifferent environments.
  • Providestagging to categorize andselect test cases to be executed.
  • Enables easy integration with source control:test suites are just filesand directories that can be versioned with the production code.
  • Providestest-case andtest-suite -level setup and teardown.
  • The modular architecture supports creating tests even for applications withseveral diverse interfaces.

1.1.2   High-level architecture

Robot Framework is a generic, application and technology independentframework. It has a highly modular architecture illustrated in thediagram below.

src/GettingStarted/architecture.png

Robot Framework architecture

Thetest data is in simple, easy-to-edit tabular format. WhenRobot Framework is started, it processes the data,executes testcases and generates logs and reports. The core framework does notknow anything about the target under test, and the interaction with itis handled bylibraries. Libraries can either use applicationinterfaces directly or use lower level test tools as drivers.

1.1.3   Screenshots

Following screenshots show examples of thetest data and createdreports andlogs.

src/GettingStarted/testdata_screenshots.png

Test case file

src/GettingStarted/screenshots.png

Reports and logs

1.1.4   Getting more information

Project pages

The number one place to find more information about Robot Frameworkand the rich ecosystem around it ishttp://robotframework.org.Robot Framework itself is hosted onGitHub.

Mailing lists

There are several Robot Framework mailing lists where to ask andsearch for more information. The mailing list archives are open foreveryone (including the search engines) and everyone can also jointhese lists freely. Only list members can send mails, though, and toprevent spam new users are moderated which means that it might take alittle time before your first message goes through. Do not be afraidto send question to mailing lists but rememberHow To Ask QuestionsThe Smart Way.

robotframework-users
General discussion about all Robot Framework relatedissues. Questions and problems can be sent to this list. Used alsofor information sharing for all users.
robotframework-announce
An announcements-only mailing list where only moderators can sendmessages. All announcements are sent also to therobotframework-users mailing list so there is no need to join bothlists.
robotframework-devel
Discussion about Robot Framework development.

1.2   Copyright and license

Robot Framework is open source software provided under theApache License2.0. Robot Framework documentation such as this User Guide use theCreative Commons Attribution 3.0 Unported license. Most libraries and toolsin the larger ecosystem around the framework are also open source, but theymay use different licenses.

The full Robot Framework copyright notice is included below:

Copyright 2008-2015 Nokia NetworksCopyright 2016-     Robot Framework FoundationLicensed under the Apache License, Version 2.0 (the "License");you may not use this file except in compliance with the License.You may obtain a copy of the License at    http://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.

1.3   Installation instructions

These instructions cover installingRobot Frameworkand its preconditions on different operating systems. If you already havePython installed, you can install Robot Framework usingthe standard package managerpip:

pip install robotframework

1.3.1   Python installation

Robot Framework is implemented usingPython, and a precondition to install itis having Python or its alternative implementationPyPyinstalled. Another recommended precondition is having thepip package manageravailable.

Robot Framework requires Python 3.8 or newer. The latest version that supportsPython 3.6 and 3.7 isRobot Framework 6.1.1. If you need to use Python 2,Jython orIronPython,you can useRobot Framework 4.1.3.

Installing Python on Linux

On Linux you should have suitable Python installation withpip availableby default. If not, you need to consult your distributions documentationto learn how to install them. This is also true if you want to use some otherPython version than the one provided by your distribution by default.

To check what Python version you have installed, you can runpython --versioncommand in a terminal:

$python--versionPython3.10.13

Notice that if your distribution provides also older Python 2, runningpythonmay use that. To use Python 3, you can usepython3 command or even more versionspecific command likepython3.8. You need to use these version specific variantsalso if you have multiple Python 3 versions installed and need to pinpoint whichone to use:

$python3.11--versionPython3.11.7$python3.12--versionPython3.12.1

Installing Robot Framework directly under the system provided Pythonhas a risk that possible problems can affect the whole Python installationused also by the operating system itself. NowadaysLinux distributions typically useuser installs by default to avoid suchproblems, but users can also themselves decide to usevirtual environments.

Installing Python on Windows

On Windows Python is not available by default, but it is easy to install.The recommended way to install it is using the official Windows installers availableathttp://python.org. For other alternatives, such as installing from theMicrosoft Store, see theofficial Python documentation.

When installing Python on Windows, it is recommended to add Python toPATHto make it and tools like pip and Robot Framework easier to execute fromthe command line. When using theofficial installer, you just needto select theAdd Python 3.x to PATH checkbox on the first dialog.

To make sure Python installation has been successful and Python has beenadded toPATH, you can open the command prompt and executepython --version:

C:\>python --versionPython 3.10.9

If you install multiple Python versions on Windows, the version that is usedwhen you executepython is the one first inPATH. If you need to use others,the easiest way is using thepy launcher:

C:\>py --versionPython 3.10.9C:\>py -3.12 --versionPython 3.12.1

Installing Python on macOS

MacOS does not provide Python 3 compatible Python version by default, so itneeds to be installed separately. The recommended approach is using the officialmacOS installers available athttp://python.org. If you are using a packagemanager likeHomebrew, installing Python via it ispossible as well.

You can validate Python installation on macOS usingpython --version like onother operating systems.

PyPy installation

PyPy is an alternative Python implementation. Its main advantage over thestandard Python implementation is that it can be faster and use less memory,but this depends on the context where and how it is used. If execution speedis important, at least testing PyPy is probably a good idea.

Installing PyPy is a straightforward procedure and you can find both installersand installation instructions athttp://pypy.org. To validate that PyPy installationwas successful, runpypy --version orpypy3 --version.

Note

Using Robot Framework with PyPy is officially supported only on Linux.

ConfiguringPATH

ThePATH environment variable lists directories where commands executed ina system are searched from. To make using Python,pip and Robot Framework easierfrom the command line, it is recommended to add the Python installation directoryas well as the directory where commands likepip androbot are installedintoPATH.

When using Python on Linux or macOS, Python and tools installed with it should beautomatically inPATH. If you nevertheless need to updatePATH, youtypically need to edit some system wide or user specific configuration file.Which file to edit and how depends on the operating system and you need toconsult its documentation for more details.

On Windows the easiest way to make surePATH is configured correctly issetting theAdd Python 3.x to PATH checkbox whenrunning the installer.To manually modifyPATH on Windows, follow these steps:

  1. FindEnvironment Variables underSettings. There are variables affectingthe whole system and variables affecting only the current user. Modifyingthe former will require admin rights, but modifying the latter is typicallyenough.
  2. SelectPATH (often written likePath) and clickEdit. If you areediting user variables andPATH does not exist, clickNew instead.
  3. Add both the Python installation directory and theScripts directoryunder the installation directory intoPATH.
  4. Exit the dialog withOk to save the changes.
  5. Start a new command prompt for the changes to take effect.

1.3.2   Installing using pip

These instructions cover installing Robot Framework usingpip, the standardPython package manager. If you are using some other package manager likeConda, you can use it instead but need to study itsdocumentation for instructions.

When installing Python, you typically get pip installed automatically. Ifthat is not the case, you need to check the documentation of that Pythoninstallation for instructions how to install it separately.

Runningpip command

Typically you use pip by running thepip command, but on Linux you may needto usepip3 or even more Python version specific variant likepip3.8instead. When runningpip or any of its variants, the pip version that isfound first inPATH will be used. If you have multiple Python versionsinstalled, you may need to pinpoint which exact version you want to use.This is typically easiest done by runningpython -m pip and substitutingpython with the Python version you want to use.

To make sure you have pip available, you can runpip --version or equivalent.

Examples on Linux:

$pip--versionpip23.2.1from...(python3.10)$python3.12-mpip--versionpip23.3.1from...(python3.12)

Examples on Windows:

C:\> pip --versionpip 23.2.1 from ... (python 3.10)C:\> py -m 3.12 -m pip --versionpip 23.3.2 from ... (python 3.12)

In the subsequent sections pip is always run using thepip command. You mayneed to use some of the other approaches explained above in your environment.

Installing and uninstalling Robot Framework

The easiest way to use pip is by letting it find and download packages itinstalls from thePython Package Index (PyPI), but it can also installpackages downloaded from the PyPI separately. The most common usages areshown below andpip documentation has more information and examples.

# Install the latest version (does not upgrade)pipinstallrobotframework# Upgrade to the latest stable versionpipinstall--upgraderobotframework# Upgrade to the latest version even if it is a pre-releasepipinstall--upgrade--prerobotframework# Install a specific versionpipinstallrobotframework==7.0# Install separately downloaded package (no network connection needed)pipinstallrobotframework-7.0-py3-none-any.whl# Install latest (possibly unreleased) code directly from GitHubpipinstallhttps://github.com/robotframework/robotframework/archive/master.zip# Uninstallpipuninstallrobotframework

1.3.3   Installing from source

Another installation alternative is getting Robot Framework source codeand installing it using the providedsetup.py script. This approach isrecommended only if you do not havepip available for some reason.

You can get the source code by downloading a source distribution packagefromPyPI and extracting it. An alternative is cloning theGitHubrepository and checking out the needed release tag.

Once you have the source code, you can install it with the following command:

pythonsetup.pyinstall

Thesetup.py script accepts several arguments allowing, for example,installation into a non-default location that does not require administrativerights. It is also used for creating different distribution packages. Runpython setup.py --help for more details.

1.3.4   Verifying installation

To make sure that the correct Robot Framework version has been installed, runthe following command:

$robot--versionRobotFramework7.0(Python3.10.3onlinux)

If running these commands fails with a message saying that the command isnot found or recognized, a good first step is double-checking thePATHconfiguration.

If you have installed Robot Framework under multiple Python versions,runningrobot will execute the one first inPATH. To select explicitly,you can runpython -m robot and substitutepython with the right Pythonversion.

$python3.12-mrobot--versionRobotFramework7.0(Python3.12.1onlinux)C:\>py-3.11-mrobot--versionRobotFramework7.0(Python3.11.7onwin32)

1.3.5   Virtual environments

Pythonvirtual environments allow Python packages to be installed inan isolated location for a particular system or application, rather thaninstalling all packages into the same global location. They havetwo main use cases:

  • Install packages needed by different projects into their own environments.This avoids conflicts if projects need different versions of same packages.
  • Avoid installing everything under the global Python installation. This isespecially important on Linux where the global Python installation may beused by the distribution itself and messing it up can cause severe problems.

1.4   Demonstrations

There are several demo projects that introduce Robot Framework and help gettingstarted with it.

Quick Start Guide
Introduces the most important features of Robot Framework and acts asan executable demo.
Robot Framework demo
Simple example test cases. Demonstrates also creating custom test libraries.
Web testing demo
Demonstrates how to create tests and higher level keywords. The systemunder test is a simple web page that is tested usingSeleniumLibrary.
ATDD with Robot Framework
Demonstrates how to use Robot Framework when followingAcceptance Test Driven Development (ATDD) process.

2   Creating test data

2.1   Test data syntax

This section covers Robot Framework's overall test data syntax. The followingsections will explain how to actually create test cases, test suites and so on.Although this section mostly uses termtest, the same rules apply alsowhencreating tasks.

2.1.1   Files and directories

The hierarchical structure for arranging test cases is built as follows:

  • Test cases are created insuite files.
  • A test case file automatically creates atest suite containingthe test cases in that file.
  • A directory containing test case files forms a higher-level testsuite. Such asuite directory has suites created from testcase files as its child test suites.
  • A test suite directory can also contain other test suite directories,and this hierarchical structure can be as deeply nested as needed.
  • Test suite directories can have a specialinitialization fileconfiguring the created test suite.

In addition to this, there are:

Test case files, test suite initialization files and resource files areall created using Robot Framework test data syntax. Test libraries andvariable files are created using "real" programming languages, mostoften Python.

2.1.2   Test data sections

Robot Framework data is defined in different sections, often alsocalled tables, listed below:

Different sections in data
SectionUsed for
Settings
2) Defining metadata fortest suitesandtest cases.
VariablesDefiningvariables that can be usedelsewhere in the test data.
Test CasesCreating test cases from availablekeywords.
TasksCreating tasks using availablekeywords. Single file can only containeither tests or tasks.
KeywordsCreating user keywords from existinglower-level keywords
CommentsAdditional comments or data. Ignored byRobot Framework.

Different sections are recognized by their header row. The recommendedheader format is*** Settings ***, but the header is case-insensitive,surrounding spaces are optional, and the number of asterisk characters canvary as long as there is at least one asterisk in the beginning. For example,also*settings would be recognized as a section header.

Robot Framework supports also singular headers like*** Setting ***, but thatsupport was deprecated in Robot Framework 6.0. There is a visible deprecationwarning starting from Robot Framework 7.0 and singular headers will eventuallynot be supported at all.

The header row can contain also other data than the actual section header.The extra data must be separated from the section header using the dataformat dependent separator, typically two or more spaces. These extra headersare ignored at parsing time, but they can be used for documentingpurposes. This is especially useful when creating test cases using thedata-driven style.

Possible data before the first section is ignored.

Note

Section headers can belocalized. See theTranslations appendix forsupported translations.

2.1.3   Supported file formats

The most common approach to create Robot Framework data is using thespace separated format where pieces of the data, such as keywordsand their arguments, are separated from each others with two or more spaces.An alternative is using thepipe separated format where the separator isthe pipe character surrounded with spaces (|).

Suite files typically use the.robot extension, but what files areparsedcan be configured.Resource files can use the.robotextension as well, but using the dedicated.resource extension isrecommended and may be mandated in the future. Files containing non-ASCIIcharacters must be saved using the UTF-8 encoding.

Robot Framework supports alsoreStructuredText files so that normalRobot Framework data isembedded into code blocks. Only files withthe.robot.rst extension are parsed by default. If you wouldrather use just.rst or.rest extension, that needs to beconfigured separately.

Robot Framework data can also be created in theJSON format that is targetedmore for tool developers than normal Robot Framework users. Only JSON fileswith the custom.rbt extension are parsed by default.

Earlier Robot Framework versions supported data also in HTML and TSV formats.The TSV format still works if the data is compatible with thespace separatedformat, but the support for the HTML format has been removed altogether.If you encounter such data files, you need to convert them to the plain textformat to be able to use them with Robot Framework 3.2 or newer. The easiestway to do that is using theTidy tool, but you must use the version includedwith Robot Framework 3.1 because newer versions do not understand the HTMLformat at all.

Space separated format

When Robot Framework parses data, it first splits the data to lines and thenlines to tokens such as keywords and arguments. When using the spaceseparated format, the separator between tokens is two or more spaces oralternatively one or more tab characters. In addition to the normal ASCIIspace, any Unicode character considered to be a space (e.g. no-break space)works as a separator. The number of spaces used as separator can vary, aslong as there are at least two, making it possible to align the data nicelyin settings and elsewhere when it makes the data easier to understand.

*** Settings ***DocumentationExample using the space separated format.LibraryOperatingSystem*** Variables ***${MESSAGE}Hello, world!*** Test Cases ***My Test    [Documentation]Example test.Log    ${MESSAGE}My Keyword    ${CURDIR}Another TestShould Be Equal    ${MESSAGE}Hello, world!*** Keywords ***My Keyword    [Arguments]    ${path}Directory Should Exist    ${path}

Because tabs and consecutive spaces are considered separators, they mustbe escaped if they are needed in keyword arguments or elsewherein the actual data. It is possible to use special escape syntax like\t for tab and\xA0 for no-break space as well asbuilt-in variables${SPACE} and${EMPTY}. See theEscaping section for details.

Tip

Although using two spaces as a separator is enough, it is recommendedto use four spaces to make the separator easier to recognize.

Note

Prior to Robot Framework 3.2, non-ASCII spaces used in the datawere converted to ASCII spaces during parsing. Nowadays all datais preserved as-is.

Pipe separated format

The biggest problem of the space delimited format is that visuallyseparating keywords from arguments can be tricky. This is a problemespecially if keywords take a lot of arguments and/or argumentscontain spaces. In such cases the pipe delimited variant canwork better because it makes the separator more visible.

One file can contain both space separated and pipe separated lines.Pipe separated lines are recognized by the mandatory leading pipe character,but the pipe at the end of the line is optional. There must always be atleast one space or tab on both sides of the pipe except at the beginning andat the end of the line. There is no need to align the pipes, but that oftenmakes the data easier to read.

|*** Settings ***   ||Documentation      |Example using the pipe separated format.|Library            |OperatingSystem|*** Variables ***  || ${MESSAGE}         |Hello, world!|*** Test Cases *** |                 |               ||My Test            | [Documentation] |Example test. ||                    |Log             | ${MESSAGE}    ||                    |My Keyword      | ${CURDIR}     ||Another Test       |Should Be Equal | ${MESSAGE}    |Hello, world!|*** Keywords ***   |                        |         ||My Keyword         | [Arguments]            | ${path} ||                    |Directory Should Exist | ${path} |

When using the pipe separated format, consecutive spaces or tabs insidearguments do not need to be escaped. Similarly empty columns do not needto be escaped exceptif they are at the end. Possible pipes surrounded byspaces in the actual test data must be escaped with a backslash, though:

|*** Test Cases *** |                 |                 |                      ||Escaping Pipe      | ${file count} = |Execute Command |ls -1 *.txt \| wc -l ||                    |Should Be Equal | ${file count}   |42                   |

Note

Preserving consecutive spaces and tabs in arguments is newin Robot Framework 3.2. Prior to it non-ASCII spaces used inthe data were also converted to ASCII spaces.

reStructuredText format

reStructuredText (reST) is an easy-to-read plain text markup syntax thatis commonly used for documentation of Python projects, including Python itselfas well as this User Guide. reST documents are most often compiled to HTML,but also other output formats are supported. Using reST with Robot Frameworkallows you to mix richly formatted documents and test data in a concise textformat that is easy to work with using simple text editors, diff tools, andsource control systems.

Note

UsingreStructuredText files with Robot Framework requires thePythondocutils module to be installed.

When using Robot Framework with reStructuredText files, normal Robot Frameworkdata is embedded to so called code blocks. In standard reST code blocks aremarked using thecode directive, but Robot Framework supports alsocode-block orsourcecode directives used by theSphinx tool.

reStructuredText example------------------------This text is outside code blocks and thus ignored...code::robotframework*** Settings ***DocumentationExample using the reStructuredText format.LibraryOperatingSystem*** Variables ***${MESSAGE}Hello, world!*** Test Cases ***My Test    [Documentation]Example test.Log    ${MESSAGE}My Keyword    ${CURDIR}Another TestShould Be Equal    ${MESSAGE}Hello, world!Also this text is outside code blocks and ignored. Code blocks notcontaining Robot Framework data are ignored as well...code::robotframework# Both space and pipe separated formats are supported.|*** Keywords ***  |                        |         ||My Keyword        | [Arguments]            | ${path} ||                   |Directory Should Exist | ${path} |..code::python# This code block is ignored.defexample():print('Hello, world!')

Robot Framework supports reStructuredText files using.robot.rst,.rst and.rest extensions. To avoid parsing unrelatedreStructuredText files, only files with the.robot.rst extensionare parsed by default when executing a directory. Parsing files withother extensionscan be enabled by using either--parseincludeor--extension option.

When Robot Framework parses reStructuredText files, errors below levelSEVERE are ignored to avoid noise about possible non-standard directivesand other such markup. This may hide also real errors, but they can be seenwhen processing files using reStructuredText tooling normally.

Note

Parsing.robot.rst files automatically is new inRobot Framework 6.1.

JSON format

Robot Framework supports data also in theJSON format. This format is designedmore for tool developers than for regular Robot Framework users and it is notmeant to be edited manually. Its most important use cases are:

  • Transferring data between processes and machines. A suite can be convertedto JSON in one machine and recreated somewhere else.
  • Saving a suite, possibly a nested suite, constructed from normal Robot Frameworkdata into a single JSON file that is faster to parse.
  • Alternative data format for external tools generating tests or tasks.

Note

The JSON data support is new in Robot Framework 6.1 and it can beenhanced in future Robot Framework versions. If you have an enhancementidea or believe you have encountered a bug, please submit anissueor start a discussion thread on the#devel channel on ourSlack.

Converting suite to JSON

A suite structure can be serialized into JSON by using theTestSuite.to_jsonmethod. When used without arguments, it returns JSON data as a string, butit also accepts a path or an open file where to write JSON data along withconfiguration options related to JSON formatting:

fromrobot.runningimportTestSuite# Create suite based on data on the file system.suite=TestSuite.from_file_system('/path/to/data')# Get JSON data as a string.data=suite.to_json()# Save JSON data to a file with custom indentation.suite.to_json('data.rbt',indent=2)

If you would rather work with Python data and then convert that to JSONor some other format yourself, you can useTestSuite.to_dict instead.

Creating suite from JSON

A suite can be constructed from JSON data using theTestSuite.from_jsonmethod. It works both with JSON strings and paths to JSON files:

fromrobot.runningimportTestSuite# Create suite from JSON data in a file.suite=TestSuite.from_json('data.rbt')# Create suite from a JSON string.suite=TestSuite.from_json('{"name": "Suite", "tests": [{"name": "Test"}]}')# Execute suite. Notice that log and report needs to be created separately.suite.run(output='example.xml')

If you have data as a Python dictionary, you can useTestSuite.from_dictinstead. Regardless of how a suite is recreated, it exists only in memory andoriginal data files on the file system are not recreated.

As the above example demonstrates, the created suite can be executed usingtheTestSuite.run method. It may, however, be easier to execute a JSON filedirectly as explained in the following section.

Executing JSON files

When executing tests or tasks using therobot command, JSON files withthe custom.rbt extension are parsed automatically. This includesrunning individual JSON files likerobot tests.rbt and running directoriescontaining.rbt files. If you would rather use the standard.json extension, you need toconfigure which files are parsed.

Adjusting suite source

Suite source in the data got fromTestSuite.to_json andTestSuite.to_dictis in absolute format. If a suite is recreated later on a different machine,the source may thus not match the directory structure on that machine. Toavoid that, it is possible to use theTestSuite.adjust_source method tomake the suite source relative before getting the data and add a correct rootdirectory after the suite is recreated:

fromrobot.runningimportTestSuite# Create a suite, adjust source and convert to JSON.suite=TestSuite.from_file_system('/path/to/data')suite.adjust_source(relative_to='/path/to')suite.to_json('data.rbt')# Recreate suite elsewhere and adjust source accordingly.suite=TestSuite.from_json('data.rbt')suite.adjust_source(root='/new/path/to')
JSON structure

Imports, variables and keywords created in suite files are included in thegenerated JSON along with tests and tasks. The exact JSON structure is documentedin therunning.jsonschema file.

2.1.4   Rules for parsing the data

Ignored data

When Robot Framework parses the test data files, it ignores:

  • All data before the firsttest data section.
  • Data in theComments section.
  • All empty rows.
  • All empty cells at the end of rows when using thepipe separated format.
  • All single backslashes (\) when not used forescaping.
  • All characters following the hash character (#), when it is the firstcharacter of a cell. This means that hash marks can be used to entercomments in the test data.

When Robot Framework ignores some data, this data is not available inany resulting reports and, additionally, most tools used with RobotFramework also ignore them. To add information that is visible inRobot Framework outputs, place it to the documentation or other metadata oftest cases or suites, or log it with theBuiltIn keywordsLog orComment.

Escaping

The escape character in Robot Framework test data is the backslash(\) and additionallybuilt-in variables${EMPTY} and${SPACE}can often be used for escaping. Different escaping mechanisms arediscussed in the sections below.

Escaping special characters

The backslash character can be used to escape special charactersso that their literal values are used.

Escaping special characters
CharacterMeaningExamples
\$Dollar sign, never starts ascalar variable.\${notvar}
\@At sign, never starts alist variable.\@{notvar}
\&Ampersand, never starts adictionary variable.\&{notvar}
\%Percent sign, never starts anenvironment variable.\%{notvar}
\#Hash sign, never starts acomment.\# not comment
\=Equal sign, never part ofnamed argument syntax.not\=named
\|Pipe character, not a separator in thepipe separated format.ls -1 *.txt \| wc -l
\\Backslash character, never escapes anything.c:\\temp, \\${var}
Forming escape sequences

The backslash character also allows creating special escape sequences that arerecognized as characters that would otherwise be hard or impossible to createin the test data.

Escape sequences
SequenceMeaningExamples
\nNewline character.first line\n2nd line
\rCarriage return charactertext\rmore text
\tTab character.text\tmore text
\xhhCharacter with hex valuehh.null byte: \x00, ä: \xE4
\uhhhhCharacter with hex valuehhhh.snowman: \u2603
\UhhhhhhhhCharacter with hex valuehhhhhhhh.love hotel: \U0001f3e9

Note

All strings created in the test data, including characters like\x02, are Unicode and must be explicitly converted tobyte strings if needed. This can be done, for example, usingConvert To Bytes orEncode String To Bytes keywordsinBuiltIn andString libraries, respectively, or withsomething likevalue.encode('UTF-8') in Python code.

Note

If invalid hexadecimal values are used with\x,\uor\U escapes, the end result is the original value withoutthe backslash character. For example,\xAX (not hex) and\U00110000 (too large value) result withxAXandU00110000, respectively. This behavior may change inthe future, though.

Note

Built-in variable${\n} can be used if operating systemdependent line terminator is needed (\r\n on Windows and\n elsewhere).

Handling empty values

When using thespace separated format, the number of spaces used asa separator can vary and thus empty values cannot be recognized unless theyare escaped. Empty cells can be escaped either with the backslash characteror withbuilt-in variable${EMPTY}. The latter is typically recommendedas it is easier to understand.

*** Test Cases ***Using backslashDo Somethingfirst arg\Do Something\second argUsing${EMPTY}Do Somethingfirst arg    ${EMPTY}Do Something    ${EMPTY}second arg

When using thepipe separated format, empty values need to be escapedonly when they are at the end of the row:

|*** Test Cases *** |              |           |            ||Using backslash    |Do Something |first arg |\          ||                    |Do Something |           |second arg ||                    |              |           |            ||Using${EMPTY}     |Do Something |first arg | ${EMPTY}   ||                    |Do Something |           |second arg |
Handling spaces

Spaces, especially consecutive spaces, as part of arguments for keywords orneeded otherwise are problematic for two reasons:

In these cases spaces need to be escaped. Similarly as when escaping emptyvalues, it is possible to do that either by using the backslash character orby using thebuilt-in variable${SPACE}.

Escaping spaces examples
Escaping with backslashEscaping with${SPACE}Notes
\ leading space${SPACE}leading space 
trailing space \trailing space${SPACE}Backslash must be after the space.
\ \${SPACE}Backslash needed on both sides.
consecutive \ \ spacesconsecutive${SPACE * 3}spacesUsingextended variable syntax.

As the above examples show, using the${SPACE} variable often makes thetest data easier to understand. It is especially handy in combination withtheextended variable syntax when more than one space is needed.

Dividing data to several rows

If there is more data than readily fits a row, it is possible to split itand start continuing rows with ellipsis (...). Ellipses can be indentedto match the indentation of the starting row and they must always be followedby the normal test data separator.

In most places split lines have exact same semantics as lines that are notsplit. Exceptions to this rule aresuite,test andkeyword documentationas wellsuite metadata. With them split values are automaticallyjoined together with the newline character to ease creating multilinevalues.

The... syntax allows also splitting variables in theVariable section.When long scalar variables (e.g.${STRING}) are split to multiple rows,the final value is got by concatenating the rows together. The separator isa space by default, but that can be changed by starting the value withSEPARATOR=<sep>.

Splitting lines is illustrated in the following two examples containingexactly same data without and with splitting.

*** Settings ***DocumentationHere we have documentation for this suite.\nDocumentation is often quite long.\n\nIt can also contain multiple paragraphs.Test Tagstest tag 1test tag 2test tag 3test tag 4test tag 5*** Variables ***${STRING}This is a long string. It has multiple sentences. It does not have newlines.${MULTILINE}This is a long multiline string.\nThis is the second line.\nThis is the third and the last line.@{LIST}thislistisquitelonganditems in it can also be long&{DICT}first=This value is pretty long.second=This value is even longer. It has two sentences.*** Test Cases ***Example    [Tags]youprobablydonothavethismanytagsinreallifeDo Xfirst argumentsecond argumentthird argumentfourth argumentfifth argumentsixth argument    ${var} =Get Xfirst argument passed to this keyword is pretty longsecond argument passed to this keyword is long too
*** Settings ***DocumentationHere we have documentation for this suite....Documentation is often quite long.......It can also contain multiple paragraphs.Test Tagstest tag 1test tag 2test tag 3...test tag 4test tag 5*** Variables ***${STRING}This is a long string....It has multiple sentences....It does not have newlines.${MULTILINE}SEPARATOR=\n...This is a long multiline string....This is the second line....This is the third and the last line.@{LIST}thislistisquitelongand...items in it can also be long&{DICT}first=This value is pretty long....second=This value is even longer. It has two sentences.*** Test Cases ***Example    [Tags]youprobablydonothavethismany    ...tagsinreallifeDo Xfirst argumentsecond argumentthird argument    ...fourth argumentfifth argumentsixth argument    ${var} =Get X    ...first argument passed to this keyword is pretty long    ...second argument passed to this keyword is long too

2.1.5   Localization

Robot Framework localization efforts were started in Robot Framework 6.0that allowed translation ofsection headers,settings,Given/When/Then prefixes used in Behavior Driven Development (BDD), andtrue and false strings used in automatic Boolean argument conversion.The plan is to extend localization support in the future, for example,to log and report and possibly also to control structures.

This section explains how toactivate languages, whatbuilt-in languagesare supported, how to createcustom language files and how new translationscan becontributed.

Enabling languages

Using command line option

The main mechanism to activate languages is specifying them from the command lineusing the--language option. When enablingbuilt-in languages,it is possible to use either the language name likeFinnish or the languagecode likefi. Both names and codes are case and space insensitive and alsothe hyphen (-) is ignored. To enable multiple languages, the--language option needs to be used multiple times:

robot --language Finnish testit.robotrobot --language pt --language ptbr testes.robot

The same--language option is also used when activatingcustom language files. With them the value can be either a path to the file or,if the file is in themodule search path, the module name:

robot --language Custom.py tests.robotrobot --language MyLang tests.robot

For backwards compatibility reasons, and to support partial translations,English is always activated automatically. Future versions may allow disablingit.

Pre-file configuration

It is also possible to enable languages directly in data files by havinga lineLanguage: <value> (case-insensitive) before any of the sectionheaders. The value after the colon is interpreted the same way as withthe--language option:

Language: Finnish*** Asetukset ***Dokumentaatio        Example using Finnish.

If there is a need to enable multiple languages, theLanguage: linecan be repeated. These configuration lines cannot be in comments so something like# Language: Finnish has no effect.

Due to technical limitations, the per-file language configuration affects alsoparsing subsequent files as well as the whole execution. Thisbehavior is likely to change in the future andshould not be relied upon.If you use per-file configuration, use it with all files or enable languagesglobally with the--language option.

Built-in languages

The following languages are supported out-of-the-box. Click the language nameto see the actual translations:

All these translations have been provided by the awesome Robot Frameworkcommunity. If a language you are interested in is not included, you canconsidercontributing it!

Custom language files

If a language you would need is not available as a built-in language, or youwant to create a totally custom language for some specific need, you can easilycreate a custom language file. Language files are Python files that containone or more language definitions that are all loaded when the language fileis taken into use. Language definitions are created by extending therobot.api.Language base class and overriding class attributes as needed:

fromrobot.apiimportLanguageclassExample(Language):test_cases_header='Validations'tags_setting='Labels'given_prefixes=['Assuming']true_strings=['OK','\N{THUMBS UP SIGN}']

Assuming the above code would be in fileexample.py, a path to thatfile or just the module nameexample could be used when the language fileisactivated.

The above example adds only some of the possible translations. That is finebecause English is automatically enabled anyway. Most values must be specifiedas strings, but BDD prefixes and true/false strings allow more than one valueand must be given as lists. For more examples, see Robot Framework's internallanguages module that contains theLanguage class as well as all built-inlanguage definitions.

Contributing translations

If you want to add translation for a new language or enhance existing, headtoCrowdin that we use for collaboration. For more details, see theseparateLocalization project, and for questions and free discussion jointhe#localization channel on ourSlack.

2.1.6   Style

Robot Framework syntax creates a simple programming language, and similarly as withother languages, it is important to think about the coding style. Robot Frameworksyntax is pretty flexible on purpose, but there are some generally recommendedconventions:

  • Four space indentation.
  • Four space separation between keywords and arguments, settings and their values, etc...In some cases it makes sense to use more than four spaces.For example when aligning values in the Settings or Variables section orindata-driven style.
  • Globalvariables using capital letters like${EXAMPLE} and local variablesusing lower-case letters like${example}.
  • Consistency within a single file and preferably within the whole project.

One case where there currently is no strong convention is keyword capitalization.Robot Framework itself typically uses title case likeExample Keyword indocumentation and elsewhere, and this style is often used in Robot Framework dataas well. It does not work too well with longer, sentence-like keywords such asLog into system as an admin, though.

Teams and organizations using Robot Framework should have their own coding standards.The community developedRobot Framework Style Guide is an excellentstarting point that can be amended as needed. It is also possible to enforce theseconventions by using theRobocop linter and theRobotidy code formatter.

2.2   Creating test cases

This section describes the overall test case syntax. Organizing testcases intotest suites usingsuite files andsuitedirectories is discussed in the next section.

When using Robot Framework for other automation purposes than testautomation, it is recommended to createtasks instead of tests.The task syntax is for most parts identical to the test syntax,and the differences are explained in theCreating tasks section.

2.2.1   Test case syntax

Basic syntax

Test cases are constructed in test case sections from the availablekeywords. Keywords can be imported fromtest libraries orresourcefiles, or created in thekeyword section of the test case fileitself.

The first column in the test case section contains test case names. Atest case starts from the row with something in this column andcontinues to the next test case name or to the end of the section. It isan error to have something between the section headers and the firsttest.

The second column normally has keyword names. An exception to this ruleissetting variables from keyword return values, when the second andpossibly also the subsequent columns contain variable names and a keywordname is located after them. In either case, columns after the keyword namecontain possible arguments to the specified keyword.

*** Test Cases ***Valid LoginOpen Login PageInput UsernamedemoInput PasswordmodeSubmit CredentialsWelcome Page Should Be OpenSetting VariablesDo Somethingfirst argumentsecond argument    ${value} =Get Some ValueShould Be Equal    ${value}Expected value

Note

Although test case names can contain any character, using? andespecially* is not generally recommended because they areconsidered to bewildcards whenselecting test cases.For example, trying to run only a test with nameExample *like--test 'Example *' will actually run any test starting withExample.

Settings in the Test Case section

Test cases can also have their own settings. Setting names are alwaysin the second column, where keywords normally are, and their valuesare in the subsequent columns. Setting names have square brackets aroundthem to distinguish them from keywords. The available settings are listedbelow and explained later in this section.

[Documentation]
Used for specifying atest case documentation.
[Setup],[Teardown]
Specifytest setup and teardown.
[Tags]
Used fortagging test cases.
[Template]
Specifies thetemplate keyword to use. The test itself will contain onlydata to use as arguments to that keyword.
[Timeout]
Used for setting atest case timeout.Timeouts are discussed intheir own section.

Note

Setting names are case-insensitive, but the format used above isrecommended. Settings used to be also space-insensitive, but that wasdeprecated in Robot Framework 3.1 and trying to use something like[T a g s] causes an error in Robot Framework 3.2. Possible spacesbetween brackets and the name (e.g.[ Tags ]) are still allowed.

Example test case with settings:

*** Test Cases ***Test With Settings    [Documentation]Another dummy test    [Tags]dummyowner-johndoeLogHello, world!

Test case related settings in the Setting section

The Setting section can have the following test case relatedsettings. These settings are mainly default values for thetest case specific settings listed earlier.

Test Setup,Test Teardown
The default values fortest setup and teardown.
Test Tags
Tags all tests in the suite will get in addition to their possible own tags.
Test Template
The defaulttemplate keyword to use.
Test Timeout
The default value fortest case timeout.Timeouts are discussed intheir own section.

2.2.2   Using arguments

The earlier examples have already demonstrated keywords takingdifferent arguments, and this section discusses this importantfunctionality more thoroughly. How to actually implementuserkeywords andlibrary keywords with different arguments isdiscussed in separate sections.

Keywords can accept zero or more arguments, and some arguments mayhave default values. What arguments a keyword accepts depends on itsimplementation, and typically the best place to search thisinformation is keyword's documentation. In the examples in thissection the documentation is expected to be generated using theLibdoc tool, but the same information is available ondocumentation generated by generic documentation tools such aspydoc.

Positional arguments

Most keywords have a certain number of arguments that must always begiven. In the keyword documentation this is denoted by specifying theargument names separated with a comma likefirst, second,third. The argument names actually do not matter in this case, exceptthat they should explain what the argument does, but it is importantto have exactly the same number of arguments as specified in thedocumentation. Using too few or too many arguments will result in anerror.

The test below uses keywordsCreate Directory andCopyFile from theOperatingSystem library. Their arguments arespecified aspath andsource, destination, which meansthat they take one and two arguments, respectively. The last keyword,No Operation fromBuiltIn, takes no arguments.

*** Test Cases ***ExampleCreate Directory    ${TEMPDIR}/stuffCopy File    ${CURDIR}/file.txt    ${TEMPDIR}/stuffNo Operation

Default values

Arguments often have default values which can either be given ornot. In the documentation the default value is typically separatedfrom the argument name with an equal sign likename=defaultvalue. It is possible that all the arguments have defaultvalues, but there cannot be any positional arguments after argumentswith default values.

Using default values is illustrated by the example below that usesCreate File keyword which has argumentspath, content=,encoding=UTF-8. Trying to use it without any arguments or more thanthree arguments would not work.

*** Test Cases ***ExampleCreate File    ${TEMPDIR}/empty.txtCreate File    ${TEMPDIR}/utf-8.txtHyvä esimerkkiCreate File    ${TEMPDIR}/iso-8859-1.txtHyvä esimerkkiISO-8859-1

Variable number of arguments

It is also possible that a keyword accepts any number of arguments.These so calledvarargs can be combined with mandatory argumentsand arguments with default values, but they are always given afterthem. In the documentation they have an asterisk before the argumentname like*varargs.

For example,Remove Files andJoin Paths keywords fromtheOperatingSystem library have arguments*paths andbase, *parts,respectively. The former can be used with any number of arguments, butthe latter requires at least one argument.

*** Test Cases ***ExampleRemove Files    ${TEMPDIR}/f1.txt    ${TEMPDIR}/f2.txt    ${TEMPDIR}/f3.txt    @{paths} =Join Paths    ${TEMPDIR}f1.txtf2.txtf3.txtf4.txt

Named arguments

The named argument syntax makes using arguments withdefault values moreflexible, and allows explicitly labeling what a certain argument value means.Technically named arguments work exactly likekeyword arguments in Python.

Basic syntax

It is possible to name an argument given to a keyword by prefixing the valuewith the name of the argument likearg=value. This is especiallyuseful when multiple arguments have default values, as it ispossible to name only some the arguments and let others use their defaults.For example, if a keyword accepts argumentsarg1=a, arg2=b, arg3=c,and it is called with one argumentarg3=override, argumentsarg1 andarg2 get their default values, butarg3gets valueoverride. If this sounds complicated, thenamed argumentsexample below hopefully makes it more clear.

The named argument syntax is both case and space sensitive. The formermeans that if you have an argumentarg, you must use it likearg=value, and neitherArg=value norARG=valueworks. The latter means that spaces are not allowed before the=sign, and possible spaces after it are considered part of the given value.

When the named argument syntax is used withuser keywords, the argumentnames must be given without the${} decoration. For example, userkeyword with arguments${arg1}=first, ${arg2}=second must be usedlikearg2=override.

Using normal positional arguments after named arguments like, for example,| Keyword | arg=value | positional |, does not work.The relative order of the named arguments does not matter.

Named arguments with variables

It is possible to usevariables in both named argument names and values.If the value is a singlescalar variable, it is passed to the keyword as-is.This allows using any objects, not only strings, as values also when usingthe named argument syntax. For example, calling a keyword likearg=${object}will pass the variable${object} to the keyword without converting it toa string.

If variables are used in named argument names, variables are resolved beforematching them against argument names.

The named argument syntax requires the equal sign to be written literallyin the keyword call. This means that variable alone can never trigger thenamed argument syntax, not even if it has a value likefoo=bar. This isimportant to remember especially when wrapping keywords into other keywords.If, for example, a keyword takes avariable number of arguments like@{args} and passes all of them to another keyword using the same@{args}syntax, possiblenamed=arg syntax used in the calling side is not recognized.This is illustrated by the example below.

*** Test Cases ***ExampleRun Programshell=True# This will not come as a named argument to Run Process*** Keywords ***Run Program    [Arguments]    @{args}Run Processprogram.py    @{args}# Named arguments are not recognized from inside @{args}

If keyword needs to accept and pass forward any named arguments, it must bechanged to acceptfree named arguments. Seefree named argument examplesfor a wrapper keyword version that can pass both positional and namedarguments forward.

Escaping named arguments syntax

The named argument syntax is used only when the part of the argumentbefore the equal sign matches one of the keyword's arguments. It is possiblethat there is a positional argument with a literal value likefoo=quux,and also an unrelated argument with namefoo. In this case the argumentfoo either incorrectly gets the valuequux or, more likely,there is a syntax error.

In these rare cases where there are accidental matches, it is possible touse the backslash character toescape the syntax likefoo\=quux.Now the argument will get a literal valuefoo=quux. Note that escapingis not needed if there are no arguments with namefoo, but because itmakes the situation more explicit, it may nevertheless be a good idea.

Where named arguments are supported

As already explained, the named argument syntax works with keywords. Inaddition to that, it also works whenimporting libraries.

Naming arguments is supported byuser keywords and by mosttest libraries.The only exceptions are Python keywords explicitly usingpositional-only arguments.

Named arguments example

The following example demonstrates using the named arguments syntax withlibrary keywords, user keywords, and when importing theTelnet test library.

*** Settings ***LibraryTelnetprompt=$default_log_level=DEBUG*** Test Cases ***ExampleOpen connection10.0.0.42port=${PORT}alias=exampleList filesoptions=-lhList filespath=/tmpoptions=-l*** Keywords ***List files    [Arguments]    ${path}=.    ${options}=Execute commandls${options}${path}

Free named arguments

Robot Framework supportsfree named arguments, often also calledfreekeyword arguments orkwargs, similarly asPython supports **kwargs.What this means is that a keyword can receive all arguments that usethenamed argument syntax (name=value) and do not match any argumentsspecified in the signature of the keyword.

Free named arguments are supported by same keyword types thannormal namedarguments. How keywords specify that they accept free named argumentsdepends on the keyword type. For example,Python based keywords simply use**kwargs anduser keywords use&{kwargs}.

Free named arguments support variables similarly asnamed arguments. In practice that means that variablescan be used both in names and values, but the escape sign must always bevisible literally. For example, bothfoo=${bar} and${foo}=${bar} arevalid, as long as the variables that are used exist. An extra limitation isthat free argument names must always be strings.

Examples

As the first example of using free named arguments, let's take a look atRun Process keyword in theProcess library. It has a signaturecommand, *arguments, **configuration, which means that it takes the commandto execute (command), its arguments asvariable number of arguments(*arguments) and finally optional configuration parameters as free namedarguments (**configuration). The example below also shows that variableswork with free keyword arguments exactly like whenusing the named argumentsyntax.

*** Test Cases ***Free Named ArgumentsRun Processprogram.pyarg1arg2cwd=/home/userRun Processprogram.pyargumentshell=Trueenv=${ENVIRON}

SeeFree keyword arguments (**kwargs) section underCreating testlibraries for more information about using the free named arguments syntaxin your custom test libraries.

As the second example, let's create a wrapperuser keyword for running theprogram.py in the above example. The wrapper keywordRun Programaccepts all positional and named arguments and passes them forward toRun Process along with the name of the command to execute.

*** Test Cases ***Free Named ArgumentsRun Programarg1arg2cwd=/home/userRun Programargumentshell=Trueenv=${ENVIRON}*** Keywords ***Run Program    [Arguments]    @{args}    &{config}Run Processprogram.py    @{args}    &{config}

Named-only arguments

Starting from Robot Framework 3.1, keywords can accept argument that mustalways be named using thenamed argument syntax. If, for example,a keyword would accept a single named-only argumentexample, it wouldalways need to be used likeexample=value and using justvalue wouldnot work. This syntax is inspired by thekeyword-only argumentssyntax supported by Python 3.

For most parts named-only arguments work the same way asnamed arguments.The main difference is that libraries implemented with Python 2 usingthestatic library APIdo not support this syntax.

As an example of using thenamed-only arguments with user keywords, hereis a variation of theRun Program in the abovefree named argumentexamples that only supports configuringshell:

*** Test Cases ***Named-only ArgumentsRun Programarg1arg2# 'shell' is False (default)Run Programargumentshell=True# 'shell' is True*** Keywords ***Run Program    [Arguments]    @{args}    ${shell}=FalseRun Processprogram.py    @{args}shell=${shell}

Arguments embedded to keyword names

A totally different approach to specify arguments is embedding theminto keyword names. This syntax is supported by bothtest library keywordsanduser keywords.

2.2.3   Failures

When test case fails

A test case fails if any of the keyword it uses fails. Normally this means thatexecution of that test case is stopped, possibletest teardown is executed,and then execution continues from the next test case. It is also possible touse specialcontinuable failures if stopping test execution is not desired.

Error messages

The error message assigned to a failed test case is got directly from thefailed keyword. Often the error message is created by the keyword itself, butsome keywords allow configuring them.

In some circumstances, for example when continuable failures are used,a test case can fail multiple times. In that case the final error messageis got by combining the individual errors. Very long error messages areautomatically cut from the middle to keepreports easier to read, butfull error messages are always visible inlog files as messages ofthe failed keywords.

By default error messages are normal text, butthey cancontain HTML formatting. Thisis enabled by starting the error message with marker string*HTML*.This marker will be removed from the final error message shown in reportsand logs. Using HTML in a custom message is shown in the second example below.

*** Test Cases ***Normal ErrorFailThis is a rather boring example...HTML Error    ${number} =Get NumberShould Be Equal    ${number}42*HTML* Number is not my <b>MAGIC</b> number.

2.2.4   Test case name and documentation

The test case name comes directly from the Test Case section: it isexactly what is entered into the test case column. Test cases in onetest suite should have unique names. Pertaining to this, you can alsouse theautomatic variable${TEST_NAME} within the testitself to refer to the test name. It is available whenever a test isbeing executed, including all user keywords, as well as the test setupand the test teardown.

Starting from Robot Framework 3.2, possiblevariables in the test case nameare resolved so that the final name will contain the variable value. Ifthe variable does not exist, its name is left unchanged.

*** Variables ***${MAX AMOUNT}      ${5000000}*** Test Cases ***Amount cannot be larger than${MAX AMOUNT}# ...

The[Documentation] setting allows setting free formdocumentation for a test case. That text is shown in the command lineoutput and in the resulting logs and reports.If documentation gets long, it can besplit into multiple rows.It is possible to use simpleHTML formatting andvariables canbe used to make the documentation dynamic. Possible non-existingvariables are left unchanged.

*** Test Cases ***Simple    [Documentation]Simple and short documentation.No OperationMultiple lines    [Documentation]First row of the documentation.    ...    ...Documentation continues here. These rows form    ...a paragraph when shown in HTML outputs.No OperationFormatting    [Documentation]    ...This list has:    ...- *bold*    ...- _italics_    ...- link: http://robotframework.orgNo OperationVariables    [Documentation]Executed at${HOST} by${USER}No Operation

It is important that test cases have clear and descriptive names, andin that case they normally do not need any documentation. If the logicof the test case needs documenting, it is often a sign that keywordsin the test case need better names and they are to be enhanced,instead of adding extra documentation. Finally, metadata, such as theenvironment and user information in the last example above, is oftenbetter specified usingtags.

2.2.5   Tagging test cases

Using tags in Robot Framework is a simple, yet powerful mechanism forclassifying test cases and alsouser keywords. Tags are free text andRobot Framework itself has no special meaning for them except for thereserved tags discussed below. Tags can be used at least for the followingpurposes:

  • They are shown in testreports,logs and, of course, in the testdata, so they provide metadata to test cases.
  • Statistics about test cases (total, passed, failed and skipped) areautomatically collected based on them.
  • They can be used toinclude and exclude as well as toskip test cases.

There are multiple ways how to specify tags for test cases explained below:

Test Tags setting in the Settings section
All tests in a test case file with this setting always get specified tags.If this setting is used in asuite initialization file, all testsin child suites get these tags.
[Tags] setting with each test case
Tests get these tags in addition to tags specified using theTest Tagssetting. The[Tags] setting also allows removing tags set withTest Tags by using the-tag syntax.
--settag command line option
All tests get tags set with this option in addition to tags they got elsewhere.
Set Tags,Remove Tags,Fail andPass Execution keywords
TheseBuiltIn keywords can be used to manipulate tags dynamicallyduring the test execution.

Example:

*** Settings ***Test Tagsrequirement: 42smoke*** Variables ***${HOST}10.0.1.42*** Test Cases ***No own tags    [Documentation]Test has tags 'requirement: 42' and 'smoke'.No OperationOwn tags    [Documentation]Test has tags 'requirement: 42', 'smoke' and 'not ready'.    [Tags]not readyNo OperationOwn tags with variable    [Documentation]Test has tags 'requirement: 42', 'smoke' and 'host: 10.0.1.42'.    [Tags]host:${HOST}No OperationRemove common tag    [Documentation]Test has only tag 'requirement: 42'.    [Tags]-smokeNo OperationRemove common tag using a pattern    [Documentation]Test has only tag 'smoke'.    [Tags]-requirement: *No OperationSet Tags and Remove Tags keywords    [Documentation]This test has tags 'smoke', 'example' and 'another'.Set TagsexampleanotherRemove Tagsrequirement: *

As the example shows, tags can be created using variables, but otherwise theypreserve the exact name used in the data. When tags are compared, for example,to collect statistics, to select test to be executed, or to remove duplicates,comparisons are case, space and underscore insensitive.

As demonstrated by the above examples, removing tags using-tag syntax supportssimple patterns like-requirement: *. Tags starting with a hyphen have nospecial meaning otherwise than with the[Tags] setting. If there isa need to set a tag starting with a hyphen with[Tags], it is possibleto use theescaped format like\-tag.

At the moment the-tag syntax can be used for removing tags only with the[Tags] setting, but the plan is to support this functionality alsowith theTest Tags setting in Robot Framework 8.0 (#5250).Setting tags having a literal value that starts with a hyphen inTest Tagswas deprecated in Robot Framework 7.2 (#5252). The escaped format like\-tagcan be used if tags with such values are needed.

Note

TheTest Tags setting is new in Robot Framework 6.0.Earlier versions supportForce Tags andDefault Tagssettings discussed in the next section.

Note

The-tag syntax for removing tags using the[Tags] settingis new in Robot Framework 7.0.

Deprecation ofForce Tags andDefault Tags

Prior to Robot Framework 6.0, tags could be specified to tests in the Setting sectionusing two different settings:

Force Tags
All tests unconditionally get these tags. This is exactly the same asTest Tags nowadays.
Default Tags
All tests get these tags by default. If a test has[Tags],it will not get these tags.

Both of these settings still work, but they are considered deprecated.A visible deprecation warning will be added in the future, most likelyin Robot Framework 8.0, and eventually these settings will be removed.Tools likeTidy can be used to ease transition.

UpdatingForce Tags requires only renaming it toTest Tags.TheDefault Tags setting will be removed altogether, but the-tagfunctionality introduced in Robot Framework 7.0 provides same underlyingfunctionality. The following examples demonstrate the needed changes.

Old syntax:

*** Settings ***Force TagsallDefault Tagsdefault*** Test Cases ***Common only    [Documentation]Test has tags 'all' and 'default'.No OperationNo default    [Documentation]Test has only tag 'all'.    [Tags]No OperationOwn and no default    [Documentation]Test has tags 'all' and 'own'.    [Tags]ownNo Operation

New syntax:

*** Settings ***Test Tagsalldefault*** Test Cases ***Common only    [Documentation]Test has tags 'all' and 'default'.No OperationNo default    [Documentation]Test has only tag 'all'.    [Tags]-defaultNo OperationOwn and no default    [Documentation]Test has tags 'all' and 'own'.    [Tags]own-defaultNo Operation

Reserved tags

Users are generally free to use whatever tags that work in their context.There are, however, certain tags that have a predefined meaning for RobotFramework itself, and using them for other purposes can have unexpectedresults. All special tags Robot Framework has and will have in the futurehave therobot: prefix. To avoid problems, users should thus not use anytag with this prefixes unless actually activating the special functionality.The current reserved tags are listed below, but more such tags are likelyto be added in the future.

robot:continue-on-failure androbot:recursive-continue-on-failure
Used forenabling the continue-on-failure mode.
robot:stop-on-failure androbot:recursive-stop-on-failure
Used fordisabling the continue-on-failure mode.
robot:exit-on-failure
Stop the whole execution if atest with this tag fails.
robot:skip-on-failure
Mark test to beskipped if it fails.
robot:skip
Mark test to beunconditionally skipped.
robot:exclude
Mark test to beunconditionally excluded.
robot:private
Mark keyword to beprivate.
robot:no-dry-run
Mark keyword not to be executed in thedry run mode.
robot:exit
Added to tests automatically whenexecution is stopped gracefully.
robot:flatten
Enableflattening keyword during execution time.

As of RobotFramework 4.1, reserved tags are suppressed by default intag statistics. They will be shown when they are explicitlyincluded via the--tagstatinclude robot:* command line option.

2.2.6   Test setup and teardown

Robot Framework has similar test setup and teardown functionality as manyother test automation frameworks. In short, a test setup is somethingthat is executed before a test case, and a test teardown is executedafter a test case. In Robot Framework setups and teardowns are justnormal keywords with possible arguments.

A setup and a teardown are always a single keyword. If they need to take careof multiple separate tasks, it is possible to create higher-leveluserkeywords for that purpose. An alternative solution is executing multiplekeywords using theBuiltIn keywordRun Keywords.

The test teardown is special in two ways. First of all, it is executed alsowhen a test case fails, so it can be used for clean-up activities that must bedone regardless of the test case status. In addition, all the keywords in theteardown are also executed even if one of them fails. Thiscontinue on failurefunctionality can be used also with normal keywords, but inside teardowns it ison by default.

The easiest way to specify a setup or a teardown for test cases in atest case file is using theTest Setup andTestTeardown settings in the Setting section. Individual test cases canalso have their own setup or teardown. They are defined with the[Setup] or[Teardown] settings in the test casesection and they override possibleTest Setup andTest Teardown settings. Having no keyword after a[Setup] or[Teardown] setting means having nosetup or teardown. It is also possible to use valueNONE to indicate thata test has no setup/teardown.

*** Settings ***Test SetupOpen ApplicationApp ATest TeardownClose Application*** Test Cases ***Default values    [Documentation]Setup and teardown from setting sectionDo SomethingOverridden setup    [Documentation]Own setup, teardown from setting section    [Setup]Open ApplicationApp BDo SomethingNo teardown    [Documentation]Default setup, no teardown at allDo Something    [Teardown]No teardown 2    [Documentation]Setup and teardown can be disabled also with special value NONEDo Something    [Teardown]NONEUsing variables    [Documentation]Setup and teardown specified using variables    [Setup]    ${SETUP}Do Something    [Teardown]    ${TEARDOWN}

The name of the keyword to be executed as a setup or a teardown can be avariable. This facilitates having different setups or teardowns indifferent environments by giving the keyword name as a variable fromthe command line.

Note

Test suites can have a setup and teardown of theirown. A suite setup is executed before any test cases or sub testsuites in that test suite, and similarly a suite teardown isexecuted after them.

2.2.7   Test templates

Test templates convert normalkeyword-driven test cases intodata-driven tests. Whereas the body of a keyword-driven test caseis constructed from keywords and their possible arguments, test cases withtemplate contain only the arguments for the template keyword.Instead of repeating the same keyword multiple times per test and/or with alltests in a file, it is possible to use it only per test or just once per file.

Template keywords can accept both normal positional and named arguments, aswell as arguments embedded to the keyword name. Unlike with other settings,it is not possible to define a template using a variable.

Basic usage

How a keyword accepting normal positional arguments can be used as a templateis illustrated by the following example test cases. These two tests arefunctionally fully identical.

*** Test Cases ***Normal test caseExample keywordfirst argumentsecond argumentTemplated test case    [Template]Example keywordfirst argumentsecond argument

As the example illustrates, it is possible to specify thetemplate for an individual test case using the[Template]setting. An alternative approach is using theTest Templatesetting in the Setting section, in which case the template is appliedfor all test cases in that test case file. The[Template]setting overrides the possible template set in the Setting section, andan empty value for[Template] means that the test has notemplate even whenTest Template is used. It is also possibleto use valueNONE to indicate that a test has no template.

Using keywords withdefault values or acceptingvariable number of arguments,as well as usingnamed arguments andfree named arguments, work with templatesexactly like they work otherwise. Usingvariables in arguments is alsosupported normally.

Templates with multiple iterations

If a templated test case has multiple data rows in its body, the templateis applied for all the rows one by one. Thismeans that the same keyword is executed multiple times, once with dataon each row.

*** Settings ***Test TemplateExample keyword*** Test Cases ***Templated test casefirst round 1first round 2second round 1second round 2third round 1third round 2

Templated tests are special so that all iterations are executed even if oneor more of them is failed or skipped. The aggregated result of a templatedtest with multiple iterations is:

  • FAIL if any of the iterations failed.
  • PASS if there were no failures and at least one iteration passed.
  • SKIP if all iterations were skipped.

Note

It is possible to use thecontinue on failure mode also with normaltests, but with the templated tests the mode is on automatically. Ifneeded, the mode can also bedisabled with templates by using therobot:stop-on-failure tag.

Note

Running all iterations if one or more is skipped is new in RobotFramework 7.2. With earlier versions the execution stopped for thefirst skipped iteration and the test got the SKIP status regardlessof the status of the earlier iterations.

Templates with embedded arguments

Templates support a variation oftheembedded argument syntax. With templates this syntax works sothat if the template keyword has variables in its name, they are consideredplaceholders for arguments and replaced with the actual argumentsused with the template. The resulting keyword is then used without positionalarguments. This is best illustrated with an example:

*** Test Cases ***Normal test case with embedded argumentsThe result of 1 + 1 should be 2The result of 1 + 2 should be 3Template with embedded arguments    [Template]The result of${calculation} should be${expected}1 + 121 + 23*** Keywords ***The result of${calculation} should be${expected}    ${result} =Calculate    ${calculation}Should Be Equal    ${result}     ${expected}

When embedded arguments are used with templates, the number of arguments inthe template keyword name must match the number of arguments it is used with.The argument names do not need to match the arguments of the original keyword,though, and it is also possible to use different arguments altogether:

*** Test Cases ***Different argument names    [Template]The result of${foo} should be${bar}1 + 121 + 23Only some arguments    [Template]The result of${calculation} should be 31 + 24 - 1New arguments    [Template]The${meaning} of${life} should be 42result21 * 2

The main benefit of using embedded arguments with templates is thatargument names are specified explicitly. When using normal arguments,the same effect can be achieved by naming the columns that containarguments. This is illustrated by thedata-driven style example inthe next section.

Templates withFOR loops

If templates are used withFOR loops, the template is applied forall the steps inside the loop. The continue on failure mode is in usealso in this case, which means that all the steps are executed withall the looped elements even if there are failures.

*** Test Cases ***Template with FOR loop    [Template]Example keywordFOR    ${item}IN    @{ITEMS}        ${item}2nd argENDFOR    ${index}IN RANGE421st arg    ${index}END

Templates withIF/ELSE structures

IF/ELSE structures can be also used together with templates.This can be useful, for example, when used together withFOR loops tofilter executed arguments.

*** Test Cases ***Template with FOR and IF    [Template]Example keywordFOR    ${item}IN    @{ITEMS}IF  ${item} < 5            ${item}2nd argENDEND

2.2.8   Different test case styles

There are several different ways in which test cases may be written. Testcases that describe some kind ofworkflow may be written either inkeyword-driven or behavior-driven style. Data-driven style can be used to testthe same workflow with varying input data.

Keyword-driven style

Workflow tests, such as theValid Login test describedearlier, are constructed from several keywords and their possiblearguments. Their normal structure is that first the system is takeninto the initial state (Open Login Page in theValidLogin example), then something is done to the system (InputName,Input Password,Submit Credentials), andfinally it is verified that the system behaved as expected(Welcome Page Should Be Open).

Data-driven style

Another style to write test cases is thedata-driven approach wheretest cases use only one higher-level keyword, often created as auser keyword, that hides the actual test workflow. These tests arevery useful when there is a need to test the same scenario withdifferent input and/or output data. It would be possible to repeat thesame keyword with every test, but thetest template functionalityallows specifying the keyword to use only once.

*** Settings ***Test TemplateLogin with invalid credentials should fail*** Test Cases ***USERNAMEPASSWORDInvalid User Nameinvalid          ${VALID PASSWORD}Invalid Password                  ${VALID USER}invalidInvalid User Name and PasswordinvalidinvalidEmpty User Name                   ${EMPTY}         ${VALID PASSWORD}Empty Password                    ${VALID USER}    ${EMPTY}Empty User Name and Password      ${EMPTY}         ${EMPTY}

Tip

Naming columns like in the example above makes tests easier tounderstand. This is possible because on the header row othercells except the first oneare ignored.

The above example has six separate tests, one for each invaliduser/password combination, and the example below illustrates how tohave only one test with all the combinations. When usingtesttemplates, all the rounds in a test are executed even if there arefailures, so there is no real functional difference between these twostyles. In the above example separate combinations are named so it iseasier to see what they test, but having potentially large number ofthese tests may mess-up statistics. Which style to use depends on thecontext and personal preferences.

*** Test Cases ***Invalid Password    [Template]Login with invalid credentials should failinvalid          ${VALID PASSWORD}    ${VALID USER}invalidinvalidwhatever    ${EMPTY}         ${VALID PASSWORD}    ${VALID USER}    ${EMPTY}    ${EMPTY}         ${EMPTY}

Behavior-driven style

It is also possible to write test cases as requirements that also non-technicalproject stakeholders must understand. Theseexecutable requirements are acorner stone of a process commonly calledAcceptance Test Driven Development(ATDD) orSpecification by Example.

One way to write these requirements/tests isGiven-When-Then stylepopularized byBehavior Driven Development (BDD). When writing test cases inthis style, the initial state is usually expressed with a keyword starting withwordGiven, the actions are described with keyword starting withWhen and the expectations with a keyword starting withThen.Keyword starting withAnd orBut may be used if a step has morethan one action.

*** Test Cases ***Valid LoginGivenlogin page is openWhenvalid username and password are insertedandcredentials are submittedThenwelcome page should be open
IgnoringGiven/When/Then/And/But prefixes

PrefixesGiven,When,Then,And andButcan be omitted when creating keywords. For example,Given login page is openin the above example is typically implemented without the wordGivenso that the name is justLogin page is open. Omitting prefixes allows usingthe same keyword with different prefixes. For example,Welcome pageshould be open could be used asThen welcome page should be open orand welcome page should be open.

Note

These prefixes can belocalized. See theTranslations appendixfor supported translations.

Embedding data to keywords

When writing concrete examples it is useful to be able to pass actual data tokeyword implementations. This can be done byembedding arguments into keyword name.

2.3   Creating tasks

In addition to test automation, Robot Framework can be used for otherautomation purposes, includingrobotic process automation (RPA).It has always been possible, but Robot Framework 3.1 added officialsupport for automatingtasks, not only tests. For most parts creatingtasks works the same way ascreating tests and the only real differenceis in terminology. Tasks can also be organized intosuites exactly liketest cases.

2.3.1   Task syntax

Tasks are created based on the available keywords exactly like test cases,and the task syntax is in general identical to thetest case syntax.The main difference is that tasks are created in Task sectionsinstead of Test Case sections:

*** Tasks ***Process invoiceRead information from PDFValidate informationSubmit information to backend systemValidate information is visible in web UI

It is an error to have both tests and tasks in same file.

2.3.2   Task related settings

Settings that can be used in the task section are exactly the same as inthetest case section. In thesetting section it is possible to useTask Setup,Task Teardown,Task TemplateandTask Timeout instead of theirTest variants.

2.4   Creating test suites

Robot Frameworktest cases are created in test case files, which canbe organized into directories. These files and directories create ahierarchical test suite structure. Same concepts apply also whencreating tasks, but the terminology differs.

2.4.1   Suite files

Robot Framework test casesare created using test case sections insuite files, also known as test case files. Such a file automatically createsa test suite fromall the test cases it contains. There is no upper limit for how manytest cases there can be, but it is recommended to have less than ten,unless thedata-driven approach is used, where one test case consists ofonly one high-level keyword.

The following settings in the Setting section can be used to customize the suite:

Name
Used for setting a customsuite name. The default name is created basedon the file or directory name.
Documentation
Used for specifying asuite documentation.
Metadata
Used for settingfree suite metadata as name-value pairs.
Suite Setup,Suite Teardown
Specifysuite setup and teardown.

Note

Setting names are case-insensitive, but the format used above is recommended.

2.4.2   Suite directories

Test case files can be organized into directories, and thesedirectories create higher-level test suites. A test suite created froma directory cannot have any test cases directly, but it containsother test suites with test cases, instead. These directories can then beplaced into other directories creating an even higher-level suite. Thereare no limits for the structure, so test cases can be organizedas needed.

When a test directory is executed, the files and directories itcontains are processed recursively as follows:

  • Files and directories with names starting with a dot (.) or anunderscore (_) are ignored.
  • Directories with the nameCVS are ignored (case-sensitive).
  • Files insupported file formats are processed.
  • Other files are ignored.

If a file or directory that is processed does not contain any testcases, it is silently ignored (a message is written to thesyslog)and the processing continues.

Suite initialization files

A test suite created from a directory can have similar settings as a suitecreated from a test case file. Because a directory alone cannot have thatkind of information, it must be placed into a special test suite initializationfile. An initialization file name must always be of the format__init__.ext, where the extension must be one of thesupportedfile formats (typically__init__.robot).The name format is borrowed from Python, where files named in this mannerdenote that a directory is a module.

Starting from Robot Framework 6.1, it is also possible to define a suiteinitialization file for automatically created suite when starting the testexecution by giving multiplepaths.

Initialization files have the same structure and syntax as test case files,except that they cannot have test case sections and not all settings aresupported. Variables and keywords created or imported in initialization filesare not available in the lower level test suites. If you need to sharevariables or keywords, you can put them intoresource files that can beimported both by initialization and test case files.

The main usage for initialization files is specifying test suite relatedsettings similarly as insuite files, but setting sometest caserelated settings is also possible. How to use different settings in theinitialization files is explained below.

Name,Documentation,Metadata,Suite Setup,Suite Teardown
These suite specific settings work the same way in suite initialization filesas in suite files.
Test Tags
Specified tags are unconditionally set to all tests in all suite filesthis directory contains, recursively. New in Robot Framework 6.1. ThedeprecatedForce Tags needs to be used with older versions.
Test Setup,Test Teardown,Test Timeout
Set the default value for test setup/teardown or test timeout to all testcases this directory contains. Can be overridden on lower level.Notice that keywords used as setups and teardowns must be available intest case files where tests using them are. Defining keywords in theinitialization file itself is not enough.
Task Setup,Task Teardown,Task Tags,Task Timeout
Aliases forTest Setup,Test Teardown,Test TagsandTest Timeout, respectively, that can be used whencreating tasks, not tests.
Default Tags,Test Template
Not supported in initialization files.
*** Settings ***DocumentationExample suiteSuite SetupDo Something    ${MESSAGE}Test TagsexampleLibrarySomeLibrary*** Variables ***${MESSAGE}Hello, world!*** Keywords ***Do Something    [Arguments]    ${args}Some Keyword    ${arg}Another Keyword

2.4.3   Suite name

The test suite name is constructed from the file or directory name by default.The name is created so that the extension is ignored, possible underscores arereplaced with spaces, and names fully in lower case are title cased. Forexample,some_tests.robot becomesSome Tests andMy_test_directory becomesMy test directory.

The file or directory name can contain a prefix to control theexecutionorder of the suites. The prefix is separated from the base name by twounderscores and, when constructing the actual test suite name, boththe prefix and underscores are removed. For example files01__some_tests.robot and02__more_tests.robot create testsuitesSome Tests andMore Tests, respectively, andthe former is executed before the latter.

Starting from Robot Framework 6.1, it is also possible to give a custom nameto a suite by using theName setting in the Setting section:

*** Settings ***NameCustom suite name

The name of the top-level suitecan be overridden from the command line withthe--name option.

2.4.4   Suite documentation

The documentation for a test suite is set using theDocumentationsetting in the Settings section. It can be used both insuite filesand insuite initialization files. Suite documentation has exactlythe same characteristics regarding to where it is shown and how it canbe created astest case documentation. For details about the syntaxsee theDocumentation formatting appendix.

*** Settings ***DocumentationAn example suite documentation with *some* _formatting_....Long documentation can be split into multiple lines.

The documentation of the top-level suitecan be overridden fromthe command line with the--doc option.

2.4.5   Free suite metadata

In addition to documentation, suites can also have free metadata. This metadatais defined as name-value pairs in the Settings section using theMetadatasetting. It is shown in reports and logs similarly as documentation.

Name of the metadata is the first argument given to theMetadata settingand the remaining arguments specify its value. The value is handled similarly asdocumentation, which means that it supportsHTML formatting andvariables, andthat longer values can besplit into multiple rows.

*** Settings ***MetadataVersion2.0MetadataRobot Frameworkhttp://robotframework.orgMetadataPlatform           ${PLATFORM}MetadataLonger Value...Longer metadata values can be split into multiple...rows. Also *simple* _formatting_ is supported.

The free metadata of the top-level suitecan be set fromthe command line with the--metadata option.

2.4.6   Suite setup and teardown

Not onlytest cases but also test suites can have a setup anda teardown. A suite setup is executed before running any of the suite'stest cases or child test suites, and a suite teardown is executed afterthem. All test suites can have a setup and a teardown; with suites createdfrom a directory they must be specified in asuite initialization file.

Similarly as with test cases, a suite setup and teardown are keywordsthat may take arguments. They are defined in the Setting section withSuite Setup andSuite Teardown settings,respectively. Keyword names and possible arguments are located inthe columns after the setting name.

If a suite setup fails, all test cases in it and its child test suitesare immediately assigned a fail status and they are not actuallyexecuted. This makes suite setups ideal for checking preconditionsthat must be met before running test cases is possible.

A suite teardown is normally used for cleaning up after all the testcases have been executed. It is executed even if the setup of the samesuite fails. If the suite teardown fails, all test cases in thesuite are marked failed, regardless of their original execution status.Note that all the keywords in suite teardowns are executed even if oneof them fails.

The name of the keyword to be executed as a setup or a teardown can bea variable. This facilitates having different setups or teardownsin different environments by giving the keyword name as a variablefrom the command line.

2.5   Using test libraries

Test libraries contain those lowest-level keywords, often calledlibrary keywords, which actually interact with the system undertest. All test cases always use keywords from some library, oftenthrough higher-leveluser keywords. This section explains how totake test libraries into use and how to use the keywords theyprovide.Creating test libraries is described in a separatesection.

2.5.1   Importing libraries

Test libraries are typically imported using theLibrary setting,but it is also possible to use theImport Library keyword.

UsingLibrary setting

Libraries are normally imported in the Settings section using theLibrary setting with the library name or path as its value.Unlike most of the other data, the library name or pathis both case- and space-sensitive. If a library is in a package,the full name including the package name must be used.

In those cases where the library needs arguments, they are listed inthe columns after the library name. It is possible to use defaultvalues, variable number of arguments, and named arguments in testlibrary imports similarly as witharguments to keywords. Both thelibrary name and arguments can be set using variables.

*** Settings ***LibraryOperatingSystemLibrarypath/to/MyLibrary.pyLibrarymy.package.TestLibraryLibraryLibraryAcceptingArgumentsarg1arg2Library    ${LIBRARY}

It is possible to import test libraries insuite files,resource files andsuite initialization files. In all thesecases, all the keywords in the imported library are available in thatfile. With resource files, those keywords are also available in otherfiles using them.

UsingImport Library keyword

Another possibility to take a test library into use is using thekeywordImport Library from theBuiltIn library. This keywordtakes the library name or path and possible arguments similarly as theLibrary setting. Keywords from the imported library areavailable in the test suite where theImport Library keyword wasused. This approach is useful in cases where the library is notavailable when the test execution starts and only some other keywordsmake it available.

*** Test Cases ***ExampleDo SomethingImport LibraryMyLibraryarg1arg2KW From MyLibrary

2.5.2   Specifying library to import

Libraries to import can be specified either by using the library nameor the path to the library. These approaches work the same way regardlessif the library is imported using theLibrary setting or theImport Library keyword.

Using library name

The most common way to specify a test library to import is using its name.In these cases Robot Framework tries to find the class or moduleimplementing the library from themodule search path. Libraries thatare installed somehow ought to be in the module search path automatically,but with other libraries the search path may need to be configured separately.

*** Settings ***LibraryOperatingSystemLibraryCustomLibrarypossibleargumentsLibrarylibrarymodule.LibraryClass

The biggest benefit of this approach is that when the module searchpath has been configured, often using a customstart-up script,normal users do not need to think where libraries actually areinstalled. The drawback is that getting your own, possiblevery simple, libraries into the search path may require someadditional configuration.

Using physical path to library

Another mechanism for specifying the library to import is using apath to it in the file system. This path is considered relative to thedirectory where current test data file is situated similarly as pathstoresource and variable files. The main benefit of this approachis that there is no need to configure the module search path.

If the library is a file, the path to it must contain extension,i.e..py. If a library is implementedas a directory, the path to it must have a trailing forward slash (/)if the path is relative. With absolute paths the trailing slash is optional.Following examples demonstrate these different usages.

*** Settings ***LibraryPythonLibrary.pyLibraryrelative/path/PythonDirLib/possibleargumentsLibrary    ${RESOURCES}/Example.py

2.5.3   Setting custom name to library

The library name is shown in test logs before keyword names, and ifmultiple keywords have the same name, they must be used so that thekeyword name is prefixed with the library name. The library nameis got normally from the module or class name implementing it, butthere are some situations where changing it is desirable:

  • There is a need to import the same library several times withdifferent arguments. This is not possible otherwise.
  • The library name is inconveniently long.
  • You want to use variables to import different libraries indifferent environments, but refer to them with the same name.
  • The library name is misleading or otherwise poor. In this case,changing the actual name is, of course, a better solution.

The basic syntax for specifying the new name is having the textAS (case-sensitive) after the library name and thenhaving the new name after that. The specified name is shown inlogs and must be used in the test data when using keywords' full name(LibraryName.Keyword Name).

*** Settings ***Librarypackagename.TestLibASTestLibLibrary    ${LIBRARY}ASMyName

Possible arguments to the library are placed between theoriginal library name and theAS marker. The following exampleillustrates how the same library can be imported several times withdifferent arguments:

*** Settings ***LibrarySomeLibrarylocalhost1234ASLocalLibLibrarySomeLibraryserver.domain8080ASRemoteLib*** Test Cases ***ExampleLocalLib.Some Keywordsome argsecond argRemoteLib.Some Keywordanother argwhateverLocalLib.Another Keyword

Setting a custom name to a test library works both when importing alibrary in the Setting section and when using theImport Library keyword.

Note

Prior to Robot Framework 6.0 the marker to use when giving a custom nameto a library wasWITH NAME instead ofAS. The old syntax continuesto work, but it is considered deprecated and will eventually be removed.

2.5.4   Standard libraries

Some test libraries are distributed with Robot Framework and theselibraries are calledstandard libraries. TheBuiltIn library is special,because it is taken into use automatically and thus its keywords are alwaysavailable. Other standard libraries need to be imported in the same wayas any other libraries, but there is no need to install them.

Normal standard libraries

The available normal standard libraries are listed below with links to theirdocumentations:

Remote library

In addition to the normal standard libraries listed above, there isalsoRemote library that is totally different than the other standardlibraries. It does not have any keywords of its own but it works as aproxy between Robot Framework and actual test library implementations.These libraries can be running on other machines than the coreframework and can even be implemented using languages not supported byRobot Framework natively.

See separateRemote library interface section for more informationabout this concept.

2.5.5   External libraries

Any test library that is not one of the standard libraries is, bydefinition,an external library. The Robot Framework open source communityhas implemented several generic libraries, such asSeleniumLibrary andSwingLibrary, which are not packaged with the core framework. A list ofpublicly available libraries can be found fromhttp://robotframework.org.

Generic and custom libraries can obviously also be implemented by teams usingRobot Framework. SeeCreating test libraries section for more informationabout that topic.

Different external libraries can have a totally different mechanismfor installing them and taking them into use. Sometimes they may also requiresome other dependencies to be installed separately. All librariesshould have clear installation and usage documentation and they shouldpreferably automate the installation process.

2.6   Variables

2.6.1   Introduction

Variables are an integral feature of Robot Framework, and they can beused in most places in test data. Most commonly, they are used inarguments for keywords in Test Case and Keyword sections, butalso all settings allow variables in their values. A normal keywordnamecannot be specified with a variable, but theBuiltIn keywordRun Keyword can be used to get the same effect.

Robot Framework has its own variables that can be used asscalars,listsordictionaries using syntax${SCALAR},@{LIST} and&{DICT},respectively. In addition to this,environment variables can be useddirectly with syntax%{ENV_VAR}.

Variables are useful, for example, in these cases:

  • When values used in multiple places in the data change often. When using variables,you only need to make changes in one place where the variable is defined.
  • When creating system-independent and operating-system-independent data.Using variables instead of hard-coded values eases that considerably(for example,${RESOURCES} instead ofc:\resources, or${HOST}instead of10.0.0.1:8080). Because variables can beset from thecommand line when tests are started, changing system-specificvariables is easy (for example,--variable RESOURCES:/opt/resources--variable HOST:10.0.0.2:1234). This also facilitateslocalization testing, which often involves running the same testswith different localized strings.
  • When there is a need to have objects other than strings as argumentsfor keywords. This is not possible without variables, unless keywordsthemselves support argument conversion.
  • When different keywords, even in different test libraries, need tocommunicate. You can assign a return value from one keyword to avariable and pass it as an argument to another.
  • When values in the test data are long or otherwise complicated. Forexample, using${URL} is more convenient than using something likehttp://long.domain.name:8080/path/to/service?foo=1&bar=2&zap=42.

If a non-existent variable is used in the test data, the keyword usingit fails. If the same syntax that is used for variables is needed as aliteral string, it must beescaped with a backslash as in\${NAME}.

2.6.2   Using variables

This section explains how to use variables using the normal scalarvariable syntax${var}, how to expand lists and dictionarieslike@{var} and&{var}, respectively, and how to use environmentvariables like%{var}. Different ways how to create variables are discussedin the next section.

Robot Framework variables, similarly as keywords, arecase-insensitive, and also spaces and underscores areignored. However, it is recommended to use capital letters withglobal variables (for example,${PATH} or${TWO WORDS})and small letters with local variables that are only available in certaintest cases or user keywords (for example,${my var}). Much moreimportantly, though, case should be used consistently.

A variable name, such as${example}, consists of the variable identifier($,@,&,%), curly braces ({,}), and the base name between thebraces. When creating variables, there may also be avariable type definitionafter the base name like${example: int}.

The variable base name can contain any characters. It is, however, highlyrecommended to use only alphabetic characters, numbers, underscores and spaces.That is a requirement for using theextended variable syntax already now andin the future that may be required with all variables.

Scalar variable syntax

The most common way to use variables in Robot Framework test data is usingthe scalar variable syntax like${var}. When this syntax is used, thevariable name is replaced with its value as-is. Most of the time variablevalues are strings, but variables can contain any object, including numbers,lists, dictionaries, or even custom objects.

The example below illustrates the usage of scalar variables. Assumingthat the variables${GREET} and${NAME} are availableand assigned to stringsHello andworld, respectively,these two example test cases are equivalent:

*** Test Cases ***ConstantsLogHelloLogHello, world!!VariablesLog    ${GREET}Log    ${GREET},${NAME}!!

When a scalar variable is used alone without any text or other variablesaround it, like in${GREET} above, the variable is replaced withits value as-is and the value can be any object. If the variable is not usedalone, like${GREER}, ${NAME}!! above, its value is first converted intoa string and then concatenated with the other data.

Note

Variable values are used as-is without string conversion also whenpassing arguments to keywords using thenamed argumentssyntax likeargname=${var}.

The example below demonstrates the difference between having avariable in alone or with other content. First, let us assumethat we have a variable${STR} set to a stringHello,world! and${OBJ} set to an instance of the following Pythonobject:

classMyObj:def__str__(self):return"Hi, terra!"

With these two variables set, we then have the following test data:

*** Test Cases ***ObjectsKW 1    ${STR}KW 2    ${OBJ}KW 3I said "${STR}"KW 4You said "${OBJ}"

Finally, when this test data is executed, different keywords receivethe arguments as explained below:

  • KW 1 gets a stringHello, world!
  • KW 2 gets an object stored to variable${OBJ}
  • KW 3 gets a stringI said "Hello, world!"
  • KW 4 gets a stringYou said "Hi, terra!"
Scalar variables containing bytes

Variables containingbytes orbytearrays are handled slightly differentlythan other variables containing non-string values:

  • If they are used alone, everything works exactly as with other objects andtheir values are passed to keywords as-is.
  • If they are concatenated only with other variables that also contain bytes orbytearrays, the result is bytes instead of a string.
  • If they are concatenated with strings or with variables containing othertypes than bytes or bytearrays, they are converted to strings like otherobjects, but they have a different string representation than they normallyhave in Python. With Python the string representation contains surroundingquotes and ab prefix likeb'\x00', but with Robot Framework quotesand the prefix are omitted, and each byte is mapped to a Unicode code pointwith the same ordinal. In practice this is same as converting bytes to stringsusing the Latin-1 encoding. This format has a big benefit that the resultingstring can be converted back to bytes, for example, by using theBuiltInkeywordConvert To Bytes or by automaticargument conversion.

The following examples demonstrates using bytes and bytearrays would workexactly the same way. Variable${a} is expected to contain bytes\x00\x01and variable${b} bytesa\xe4.

*** Test Cases ***Bytes alone    [Documentation]Keyword gets bytes '\x00\x01'.Keyword    ${a}Bytes concatenated with bytes    [Documentation]Keyword gets bytes '\x00\x01a\xe4'.Keyword    ${a}${b}Bytes concatenated with others    [Documentation]Keyword gets string '=\x00\x01a\xe4='.Keyword=${a}${b}=

Note

Getting bytes when variables containing bytes are concatenated is newin Robot Framework 7.2. With earlier versions the result was a string.

Note

All bytes being mapped to matching Unicode code points in stringrepresentation is new Robot Framework 7.2. With earlier versions,only bytes in the ASCII range were mapped directly to code points andother bytes were represented in an escaped format.

List variable syntax

When a variable is used as a scalar like${EXAMPLE}, its value is beused as-is. If a variable value is a list or list-like, it is also possibleto use it as a list variable like@{EXAMPLE}. In this case the list is expandedand individual items are passed in as separate arguments.

This is easiest to explain with an example. Assuming that a variable${USER}contains a list with two itemsrobot andsecret, the first two of these testsare equivalent:

*** Test Cases ***ConstantsLoginrobotsecretList variableLogin    @{USER}List as scalarKeyword    ${USER}

The third test above illustrates that a variable containing a list can be usedalso as a scalar. In that test the keyword gets the whole list as a single argument.

Starting from Robot Framework 4.0, list expansion can be used in combination withlist item access making these usages possible:

*** Test Cases ***Nested container    ${nested} =Evaluate[['a', 'b', 'c'], {'key': ['x', 'y']}]Log Many    @{nested}[0]# Logs 'a', 'b' and 'c'.Log Many    @{nested}[1][key]# Logs 'x' and 'y'.Slice    ${items} =Create ListfirstsecondthirdLog Many    @{items}[1:]# Logs 'second' and  'third'.
Using list variables with other data

It is possible to use list variables with other arguments, includingother list variables.

*** Test Cases ***ExampleKeyword    @{LIST}moreargsKeyword    ${SCALAR}    @{LIST}constantKeyword    @{LIST}    @{ANOTHER}    @{ONE MORE}
Using list variables with settings

List variables can be used only with some of thesettings. They canbe used in arguments to imported libraries and variable files, butlibrary and variable file names themselves cannot be listvariables. Also with setups and teardowns list variable can not be usedas the name of the keyword, but can be used in arguments. With tag relatedsettings they can be used freely. Using scalar variables is possible inthose places where list variables are not supported.

*** Settings ***LibraryExampleLibrary      @{LIB ARGS}# This worksLibrary         ${LIBRARY}          @{LIB ARGS}# This worksLibrary         @{LIBRARY AND ARGS}# This does not workSuite SetupSome Keyword        @{KW ARGS}# This worksSuite Setup     ${KEYWORD}          @{KW ARGS}# This worksSuite Setup     @{KEYWORD AND ARGS}# This does not workTest Tags       @{TAGS}# This works

Dictionary variable syntax

As discussed above, a variable containing a list can be used as alistvariable to pass list items to a keyword as individual arguments.Similarly, a variable containing a Python dictionary or a dictionary-likeobject can be used as a dictionary variable like&{EXAMPLE}. In practicethis means that the dictionary is expanded and individual items are passed asnamed arguments to the keyword. Assuming that a variable&{USER} has avalue{'name': 'robot', 'password': 'secret'}, the first two test casesbelow are equivalent:

*** Test Cases ***ConstantsLoginname=robotpassword=secretDictionary variableLogin    &{USER}Dictionary as scalarKeyword    ${USER}

The third test above illustrates that a variable containing a dictionary can be usedalso as a scalar. In that test the keyword gets the whole dictionary as a single argument.

Starting from Robot Framework 4.0, dictionary expansion can be used in combination withdictionary item access making usages like&{nested}[key] possible.

Using dictionary variables with other data

It is possible to use dictionary variables with other arguments, includingother dictionary variables. Becausenamed argument syntax requires positionalarguments to be before named argument, dictionaries can only be followed bynamed arguments or other dictionaries.

*** Test Cases ***ExampleKeyword    &{DICT}named=argKeywordpositional    @{LIST}    &{DICT}Keyword    &{DICT}    &{ANOTHER}    &{ONE MORE}
Using dictionary variables with settings

Dictionary variables cannot generally be used with settings. The only exceptionare imports, setups and teardowns where dictionaries can be used as arguments.

*** Settings ***LibraryExampleLibrary    &{LIB ARGS}Suite SetupSome Keyword      &{KW ARGS}named=arg

Accessing list and dictionary items

It is possible to access items of subscriptable variables, e.g. lists and dictionaries,using special syntax like${var}[item] or${var}[nested][item].Starting from Robot Framework 4.0, it is also possible to use item access together withlist expansion anddictionary expansion by using syntax@{var}[item] and&{var}[item], respectively.

Note

Prior to Robot Framework 3.1, the normal item access syntax was@{var}[item]with lists and&{var}[item] with dictionaries. Robot Framework 3.1 introducedthe generic${var}[item] syntax along with some other nice enhancements andthe old item access syntax was deprecated in Robot Framework 3.2.

Accessing sequence items

It is possible to access a certain item of a variable containing asequence(e.g. list, string or bytes) with the syntax${var}[index], whereindexis the index of the selected value. Indices start from zero, negative indicescan be used to access items from the end, and trying to access an item withtoo large an index causes an error. Indices are automatically converted tointegers, and it is also possible to use variables as indices.

*** Test Cases ***Positive indexLogin    ${USER}[0]    ${USER}[1]Title Should BeWelcome${USER}[0]!Negative indexKeyword    ${SEQUENCE}[-1]Index defined as variableKeyword    ${SEQUENCE}[${INDEX}]

Sequence item access supports also thesame "slice" functionality as Pythonwith syntax like${var}[1:]. With this syntax, you do not get a singleitem, but aslice of the original sequence. Same way as with Python, you canspecify the start index, the end index, and the step:

*** Test Cases ***Start indexKeyword    ${SEQUENCE}[1:]End indexKeyword    ${SEQUENCE}[:4]Start and endKeyword    ${SEQUENCE}[2:-1]StepKeyword    ${SEQUENCE}[::2]Keyword    ${SEQUENCE}[1:-1:10]

Note

Prior to Robot Framework 3.2, item and slice access was only supportedwith variables containing lists, tuples, or other objects consideredlist-like. Nowadays all sequences, including strings and bytes, aresupported.

Accessing individual dictionary items

It is possible to access a certain value of a dictionary variablewith the syntax${NAME}[key], wherekey is the name of theselected value. Keys are considered to be strings, but non-stringskeys can be used as variables. Dictionary values accessed in thismanner can be used similarly as scalar variables.

If a dictionary is created in Robot Framework data, it is possible to accessvalues also using the attribute access syntax like${NAME.key}. See theCreating dictionaries section for more details about this syntax.

*** Test Cases ***Dictionary variable itemLogin    ${USER}[name]    ${USER}[password]Title Should BeWelcome${USER}[name]!Key defined as variableLog Many    ${DICT}[${KEY}]    ${DICT}[${42}]Attribute accessLogin    ${USER.name}    ${USER.password}Title Should BeWelcome${USER.name}!
Nested item access

Also nested subscriptable variables can be accessed using the sameitem access syntax like${var}[item1][item2]. This is especially usefulwhen working with JSON data often returned by REST services. For example,if a variable${DATA} contains[{'id': 1, 'name': 'Robot'},{'id': 2, 'name': 'Mr. X'}], this tests would pass:

*** Test Cases ***Nested item accessShould Be Equal    ${DATA}[0][name]RobotShould Be Equal    ${DATA}[1][id]      ${2}

Environment variables

Robot Framework allows using environment variables in the test data usingthe syntax%{ENV_VAR_NAME}. They are limited to string values. It ispossible to specify a default value, that is used if the environmentvariable does not exists, by separating the variable name and the defaultvalue with an equal sign like%{ENV_VAR_NAME=default value}.

Environment variables set in the operating system before the test execution areavailable during it, and it is possible to create new ones with the keywordSet Environment Variable or delete existing ones with thekeywordDelete Environment Variable, both available in theOperatingSystem library. Because environment variables are global,environment variables set in one test case can be used in other testcases executed after it. However, changes to environment variables arenot effective after the test execution.

*** Test Cases ***Environment variablesLogCurrent user:%{USER}Run    %{JAVA_HOME}${/}javacEnvironment variable with defaultSet Port    %{APPLICATION_PORT=8080}

Note

Support for specifying the default value is new in Robot Framework 3.2.

2.6.3   Creating variables

Variables can be created using different approaches discussed in this section:

In addition to this, there are various automatically availablebuilt-in variablesand alsouser keyword arguments andFOR loops create variables.

Variable section

The most common source for variables are Variable sections insuite filesandresource files. Variable sections are convenient, because theyallow creating variables in the same place as the rest of the testdata, and the needed syntax is very simple. Their main disadvantage is thatvariables cannot be created dynamically. If that is a problem,variable filescan be used instead.

Creating scalar values

The simplest possible variable assignment is setting a string into ascalar variable. This is done by giving the variable name (including${}) in the first column of the Variable section and the value inthe second one. If the second column is empty, an empty string is setas a value. Also an already defined variable can be used in the value.

*** Variables ***${NAME}Robot Framework${VERSION}2.0${ROBOT}        ${NAME}${VERSION}

It is also possible, but not obligatory,to use the equals sign= after the variable name to make assigningvariables slightly more explicit.

*** Variables ***${NAME} =Robot Framework${VERSION} =2.0

If a scalar variable has a long value, it can besplit into multiple rowsby using the... syntax. By default rows are concatenated together usinga space, but this can be changed by using aseparator configurationoption after the last value:

*** Variables ***${EXAMPLE}This value is joined...together with a space.${MULTILINE}First line....Second line....Third line....separator=\n

Theseparator option is new in Robot Framework 7.0, but also older versionssupport configuring the separator. With them the first value can contain aspecialSEPARATOR marker:

*** Variables ***${MULTILINE}SEPARATOR=\n...First line....Second line....Third line.

Both theseparator option and theSEPARATOR marker are case-sensitive.Using theseparator option is recommended, unless there is a need tosupport also older versions.

Creating lists

Creating lists is as easy as creating scalar values. Again, thevariable name is in the first column of the Variable section andvalues in the subsequent columns, but this time the variable name muststart with@ instead of$. A list can have any number of items,including zero, and items can besplit into several rows if needed.

*** Variables ***@{NAMES}MattiTeppo@{NAMES2}       @{NAMES}Seppo@{NOTHING}@{MANY}onetwothreefour...fivesixseven

Note

As discussed in theList variable syntax section, variablescontaining lists can be used as scalars like${NAMES} andby using the list expansion syntax like@{NAMES}.

Creating dictionaries

Dictionaries can be created in the Variable section similarly as lists.The differences are that the name must now start with& and that items needto be created using thename=value syntax or based on existing dictionary variables.If there are multiple items with same name, the last value has precedence.If a name contains a literal equal sign, it can beescaped with a backslash like\=.

*** Variables ***&{USER 1}name=Mattiaddress=xxxphone=123&{USER 2}name=Teppoaddress=yyyphone=456&{MANY}first=1second=${2}         ${3}=third&{EVEN MORE}    &{MANY}first=overrideempty=...=emptykey\=here=value

Note

As discussed in theDictionary variable syntax section, variablescontaining dictionaries can be used as scalars like${USER 1} andby using the dictionary expansion syntax like&{USER 1}.

Unlike with normal Python dictionaries, values of dictionaries created usingthis syntax can be accessed as attributes, which means that it is possibleto useextended variable syntax like${VAR.key}. This only works if thekey is a valid attribute name and does not match any normal attribute Pythondictionaries have, though. For example, individual value${USER}[name] canalso be accessed like${USER.name}, but using${MANY.3} is not possible.

Tip

With nested dictionaries keys are accessible like${DATA.nested.key}.

Dictionaries are also ordered. This means that if they are iterated,their items always come in the order they are defined. This can be useful, for example,if dictionaries are used aslist variables withFOR loops or otherwise.When a dictionary is used as a list variable, the actual value containsdictionary keys. For example,@{MANY} variable would have a value['first','second', 3].

Creating variable name based on another variable

Starting from Robot Framework 7.0, it is possible to create the variable namedynamically based on another variable:

*** Variables ***${X}Y${${X}}Z# Name is created based on '${X}'.*** Test Cases ***Dynamically created nameShould Be Equal    ${Y}Z

Using variable files

Variable files are the most powerful mechanism for creating differentkind of variables. It is possible to assign variables to any objectusing them, and they also enable creating variables dynamically. Thevariable file syntax and taking variable files into use is explainedin sectionResource and variable files.

Command line variables

Variables can be set from the command line either individually withthe--variable (-v) option or using the aforementioned variable fileswith the--variablefile (-V) option. Variables set from the command lineare globally available for all executed test data files, and they alsooverride possible variables with the same names in the Variable section and invariable files imported in the Setting section.

The syntax for setting individual variables is--variable name:value,wherename is the name of the variable without the${} decoration andvalueis its value. Several variables can be set by using this option several times.

--variableEXAMPLE:value--variableHOST:localhost:7272--variableUSER:robot

In the examples above, variables are set so that:

  • ${EXAMPLE} gets valuevalue, and
  • ${HOST} and${USER} get valueslocalhost:7272 androbot, respectively.

The basic syntax for takingvariable files into use from the command line is--variablefile path/to/variables.py and theTaking variable files intouse section explains this more thoroughly. What variables actually are createddepends on what variables there are in the referenced variable file.

If both variable files and individual variables are given from the command line,the latter havehigher priority.

Return values from keywords

Return values from keywords can also be assigned into variables. Thisallows communication between different keywords even in different librariesby passing created variables forward as arguments to other keywords.

Variables set in this manner are otherwise similar to any othervariables, but they are available only in thelocal scopewhere they are created. Thus it is not possible, for example, to seta variable like this in one test case and use it in another. This isbecause, in general, automated test cases should not depend on eachother, and accidentally setting a variable that is used elsewherecould cause hard-to-debug errors. If there is a genuine need forsetting a variable in one test case and using it in another, it ispossible to use theVAR syntax orSet Test/Suite/Global Variable keywordsas explained in the subsequent sections.

Assigning scalar variables

Any value returned by a keyword can be assigned to ascalar variable.As illustrated by the example below, the required syntax is very simple:

*** Test Cases ***Returning    ${x} =Get Xan argumentLogWe got${x}!

In the above example the value returned by theGet X keywordis first set into the variable${x} and then used by theLogkeyword. Having the equals sign= after the name of the assigned variable isnot obligatory, but it makes the assignment more explicit. Creatinglocal variables like this works both in test case and user keyword level.

Notice that although a value is assigned to a scalar variable, it canbe used as alist variable if it has a list-like value and as adictionaryvariable if it has a dictionary-like value.

*** Test Cases ***List assigned to scalar variable    ${list} =Create ListfirstsecondthirdLength Should Be    ${list}3Log Many    @{list}
Assigning variable items

Starting from Robot Framework 6.1, when working with variables that supportitem assignment such as lists or dictionaries, it is possible to set their valuesby specifying the index or key of the item using the syntax${var}[item]where theitem part can itself contain a variable:

*** Test Cases ***List item assignment    ${list} =Create Listonetwothreefour    ${list}[0] =Set Variablefirst    ${list}[${1}] =Set Variablesecond    ${list}[2:3] =Create Listthird    ${list}[-1] =Set VariablelastLog Many           @{list}# Logs 'first', 'second', 'third' and 'last'Dictionary item assignment    ${dict} =Create Dictionaryfirst_name=unknown    ${dict}[first_name] =Set VariableJohn    ${dict}[last_name] =Set VariableDoeLog                      ${dictionary}# Logs {'first_name': 'John', 'last_name': 'Doe'}
Creating variable name based on another variable

Starting from Robot Framework 7.0, it is possible to create the name of the assignedvariable dynamically based on another variable:

*** Test Cases ***Dynamically created name    ${x} =Set Variabley    ${${x}} =Set Variablez# Name is created based on '${x}'.Should Be Equal    ${y}z
Assigning list variables

If a keyword returns a list or any list-like object, it is possible toassign it to alist variable:

*** Test Cases ***Assign to list variable    @{list} =Create ListfirstsecondthirdLength Should Be    ${list}3Log Many    @{list}

Because all Robot Framework variables are stored in the same namespace, there isnot much difference between assigning a value to a scalar variable or a listvariable. This can be seen by comparing the above example with the earlierexample with theList assigned to scalar variable test case. The maindifferences are that when creating a list variable, Robot Frameworkautomatically verifies that the value is a list or list-like, and the storedvariable value will be a new list created from the return value. Whenassigning to a scalar variable, the return value is not verified and thestored value will be the exact same object that was returned.

Assigning dictionary variables

If a keyword returns a dictionary or any dictionary-like object, it is possibleto assign it to adictionary variable:

*** Test Cases ***Assign to dictionary variable    &{dict} =Create Dictionaryfirst=1second=${2}    ${3}=thirdLength Should Be    ${dict}3Do Something    &{dict}Log    ${dict.first}

Because all Robot Framework variables are stored in the same namespace, it wouldalso be possible to assign a dictionary into a scalar variable and use itlater as a dictionary when needed. There are, however, some concrete benefitsin creating a dictionary variable explicitly. First of all, Robot Frameworkverifies that the returned value is a dictionary or dictionary-like similarlyas it verifies that list variables can only get a list-like value.

A bigger benefit is that the value is converted into a special dictionarythat is used also whencreating dictionaries in the Variable section.Values in these dictionaries can be accessed using attribute access like${dict.first} in the above example.

Assigning multiple variables

If a keyword returns a list or a list-like object, it is possible to assignindividual values into multiple scalar variables or into scalar variables anda list variable.

*** Test Cases ***Assign multiple    ${a}    ${b}    ${c} =Get Three    ${first}    @{rest} =Get Three    @{before}    ${last} =Get Three    ${begin}    @{middle}    ${end} =Get Three

Assuming that the keywordGet Three returns a list[1, 2, 3],the following variables are created:

  • ${a},${b} and${c} with values1,2, and3, respectively.
  • ${first} with value1, and@{rest} with value[2, 3].
  • @{before} with value[1, 2] and${last} with value3.
  • ${begin} with value1,@{middle} with value[2] and${end} withvalue3.

It is an error if the returned list has more or less values than there arescalar variables to assign. Additionally, only one list variable is allowedand dictionary variables can only be assigned alone.

Automatically logging assigned variable value

To make it easier to understand what happens during execution,the beginning of value that is assigned is automatically logged.The default is to show 200 first characters, but this can be changedby using the--maxassignlength command line option whenrunning tests. If the value is zero or negative, the whole assignedvalue is hidden.

--maxassignlength1000--maxassignlength0

The reason the value is not logged fully is that it could be reallybig. If you always want to see a certain value fully, it is possibleto use theBuiltInLog keyword to log it after the assignment.

Note

The--maxassignlength option is new in Robot Framework 5.0.

VAR syntax

Starting from Robot Framework 7.0, it is possible to create variables insidetests and user keywords using theVAR syntax. TheVAR marker is case-sensitiveand it must be followed by a variable name and value. Other than the mandatoryVAR, the overall syntax is mostly the same as when creating variablesin theVariable section.

The new syntax aims to make creating variables simpler and more uniform. It isespecially indented to replace theBuiltIn keywordsSet Variable,Set Local Variable,Set Test Variable,Set Suite VariableandSet Global Variable, but it can be used instead ofCatenate,Create List andCreate Dictionary as well.

Creating scalar variables

In simple cases scalar variables are created by just giving a variable nameand its value. The value can be a hard-coded string or it can itself containa variable. If the value is long, it is possible to split it into multiplecolumns and rows. In that case parts are joined together with a space by default,but the separator to use can be specified with theseparator configurationoption. It is possible to have an optional= after the variable name the sameway as when creating variables based onreturn values from keywords and intheVariable section.

*** Test Cases ***Scalar examplesVAR    ${simple}variableVAR    ${equals} =this works tooVAR    ${variable}value contains${simple}VAR    ${sentence}This is a bit longer variable value     ...that is split into multiple rows.     ...These parts are joined with a space.VAR    ${multiline}This is another longer value.     ...This time there is a custom separator.     ...As the result this becomes a multiline string.     ...separator=\n
Creating lists and dictionaries

List and dictionary variables are created similarly as scalar variables,but the variable names must start with@ and&, respectively.When creating dictionaries, items must be specified using thename=value syntax.

*** Test Cases ***List examplesVAR    @{two items}RobotFrameworkVAR    @{empty list}VAR    @{lot of stuff}     ...first item     ...second item     ...third item     ...fourth item     ...last itemDictionary examplesVAR    &{two items}name=Robot Frameworkurl=http://robotframework.orgVAR    &{empty dict}VAR    &{lot of stuff}     ...first=1     ...second=2     ...third=3     ...fourth=4     ...last=5
Scope

Variables created with theVAR syntax are are available only within the testor user keyword where they are created. That can, however, be altered by usingthescope configuration option. Supported values are:

LOCAL
Make the variable available in the current local scope. This is the default.
TEST
Make the variable available within the current test. This includes all keywordscalled by the test. If used on the suite level, makes the variable available insuite setup and teardown, but not in tests or possible child suites.Prior to Robot Framework 7.2, using this scope on the suite level was an error.
TASK
Alias forTEST that can be used whencreating tasks.
SUITE
Make the variable available within the current suite. This includes all subsequenttests in that suite, but not tests in possible child suites.
SUITES
Make the variable available within the current suite and in its child suites.New in Robot Framework 7.1.
GLOBAL
Make the variable available globally. This includes all subsequent keywords and tests.

Although Robot Framework variables are case-insensitive, it is recommended touse capital letters with non-local variable names.

*** Variables ***${SUITE}this value is overridden*** Test Cases ***Scope exampleVAR    ${local}local valueVAR    ${TEST}test valuescope=TESTVAR    ${SUITE}suite valuescope=SUITEVAR    ${SUITES}nested suite valuescope=SUITESVAR    ${GLOBAL}global valuescope=GLOBALShould Be Equal    ${local}local valueShould Be Equal    ${TEST}test valueShould Be Equal    ${SUITE}suite valueShould Be Equal    ${SUITES}nested suite valueShould Be Equal    ${GLOBAL}global valueKeywordShould Be Equal    ${TEST}new test valueShould Be Equal    ${SUITE}new suite valueShould Be Equal    ${SUITES}new nested suite valueShould Be Equal    ${GLOBAL}new global valueScope example, part 2Should Be Equal    ${SUITE}new suite valueShould Be Equal    ${SUITES}new nested suite valueShould Be Equal    ${GLOBAL}new global value*** Keywords ***KeywordShould Be Equal    ${TEST}test valueShould Be Equal    ${SUITE}suite valueShould Be Equal    ${SUITES}nested suite valueShould Be Equal    ${GLOBAL}global valueVAR    ${TEST}new${TEST}scope=TESTVAR    ${SUITE}new${SUITE}scope=SUITEVAR    ${SUITES}new${SUITES}scope=SUITESVAR    ${GLOBAL}new${GLOBAL}scope=GLOBALShould Be Equal    ${TEST}new test valueShould Be Equal    ${SUITE}new suite valueShould Be Equal    ${SUITES}new nested suite valueShould Be Equal    ${GLOBAL}new global value
Creating variables conditionally

TheVAR syntax works withIF/ELSE structures which makes it easy to createvariables conditionally. In simple cases usinginline IF can be convenient.

*** Test Cases ***IF/ELSE exampleIF"${ENV}" == "devel"VAR    ${address}127.0.0.1VAR    ${name}demoELSEVAR    ${address}192.168.1.42VAR    ${name}robotENDInline IFIF"${ENV}" == "devel"VAR    ${name}demoELSEVAR    ${name}robot
Creating variable name based on another variable

If there is a need, variable name can also be created dynamically based onanother variable.

*** Test Cases ***Dynamic nameVAR    ${x}y# Normal assignment.VAR    ${${x}}z# Name created dynamically.Should Be Equal    ${y}z

Set Test/Suite/Global Variable keywords

Note

TheVAR syntax is recommended over these keywords when usingRobot Framework 7.0 or newer.

TheBuiltIn library has keywordsSet Test Variable,Set Suite Variable andSet Global Variable which canbe used for setting variables dynamically during the testexecution. If a variable already exists within the new scope, itsvalue will be overwritten, and otherwise a new variable is created.

Variables set withSet Test Variable keyword are availableeverywhere within the scope of the currently executed test case. Forexample, if you set a variable in a user keyword, it is available bothin the test case level and also in all other user keywords used in thecurrent test. Other test cases will not see variables set with thiskeyword. It is an error to callSet Test Variableoutside the scope of a test (e.g. in a Suite Setup or Teardown).

Variables set withSet Suite Variable keyword are availableeverywhere within the scope of the currently executed testsuite. Setting variables with this keyword thus has the same effect ascreating them using theVariable section in the test data file orimporting them fromvariable files. Other test suites, includingpossible child test suites, will not see variables set with thiskeyword.

Variables set withSet Global Variable keyword are globallyavailable in all test cases and suites executed after settingthem. Setting variables with this keyword thus has the same effect ascreating variables on the command line using the--variable and--variablefile options. Because this keyword can change variableseverywhere, it should be used with care.

Note

Set Test/Suite/Global Variable keywords set namedvariables directly intotest, suite or global variable scopeand return nothing. On the other hand, anotherBuiltIn keywordSet Variable sets local variables usingreturn values.

Variable type conversion

Variable values are typically strings, but non-string values are often neededas well. Various ways how to create variables with non-string values hasalready been discussed:

  • Variable files allow creating any kind of objects.
  • Return values from keywords can contain any objects.
  • Variables can be created based on existing variables that contain non-string values.
  • @{list} and&{dict} syntax allows creating lists and dictionaries natively.

In addition to the above, it is possible to specify the variable type like${name: int} when creating variables, and the value is converted tothe specified type automatically. This is calledvariable type conversionand how it works in practice is discussed in this section.

Note

Variable type conversion is new in Robot Framework 7.3.

Variable type syntax

The general variable types syntax is${name: type}in the data andname: type:valueon the command line. The space after the colon is mandatoryin both cases. Although variable name can in some contexts be created dynamicallybased on another variable, the type and the type separator must be always specifiedas literal values.

Variable type conversion supports the same base types that theargument conversionsupports with library keywords. For example,${number: int} means that the valueof the variable${number} is converted to an integer.

Variable type conversion supports alsospecifying multiple possible typesusing the union syntax. For example,${number: int | float} means that thevalue is first converted to an integer and, if that fails, then to a floatingpoint number.

Alsoparameterized types are supported. For example,${numbers: list[int]}means that the value is converted to a list of integers.

The biggest limitations compared to the argument conversion with librarykeywords is thatEnum andTypedDict conversions are not supported andthat custom converters cannot be used. These limitations may be lifted inthe future versions.

Note

Variable conversion is supported only when variables are created,not when they are used.

Variable conversion in data

In the data variable conversion works when creating variables in theVariable section, with theVAR syntax and based onreturn values from keywords:

*** Variables ***${VERSION: float}7.3${CRITICAL: list[int]}[3278, 5368, 5417]*** Test Cases ***Variables sectionShould Be Equal    ${VERSION}       ${7.3}Should Be Equal    ${CRITICAL}      ${{[3278, 5368, 5417]}}VAR syntaxVAR    ${number: int}42Should Be Equal    ${number}    ${42}Assignment# In simple cases the VAR syntax is more convenient.    ${number: int} =Set Variable42Should Be Equal    ${number}    ${42}# In this case conversion is more useful.    ${match}    ${version: float} =Should Match RegexpRF 7.3^RF (\\d+\\.\\d+)$Should Be Equal    ${match}RF 7.3Should Be Equal    ${version}    ${7.3}

Note

In addition to the above, variable type conversion works also withuser keyword arguments and withFOR loops. See their documentationfor more details.

Note

Variable type conversiondoes not work withSet Test/Suite/Global Variablekeywords. TheVAR syntax needs to be used instead.

Conversion with@{list} and&{dict} variables

Type conversion works also when creatinglists anddictionaries using@{list} and&{dict} syntax. With lists the type is specifiedlike@{name: type} and the type is the type of the list items. With dictionariesthe type of the dictionary values can be specified like&{name: type}. Ifthere is a need to specify also the key type, it is possible to use syntax&{name: ktype=vtype}.

*** Variables ***@{NUMBERS: int}12345&{DATES: date}rc1=2025-05-08final=2025-05-30&{PRIORITIES: int=str}3278=Critical4173=High5334=High

An alternative way to create lists and dictionaries is creating${scalar} variables,usinglist anddict types, possibly parameterizing them, and giving values asPython list and dictionary literals:

*** Variables ***${NUMBERS: list[int]}[1, 2, 3, 4, 5]${DATES: list[date]}{'rc1': '2025-05-08', 'final': '2025-05-30'}${PRIORITIES: dict[int, str]}{3278: 'Critical', 4173: 'High', 5334: 'High'}

Using Python list and dictionary literals can be somewhat complicated especiallyfor non-programmers. The main benefit of this approach is that it supports alsonested structures without needing to use temporary values. The following examplescreate the same${PAYLOAD} variable using different approaches:

*** Variables ***${PAYLOAD: dict}{'id': 1, 'name': 'Robot', 'children': [2, 13, 15]}
*** Variables ***@{CHILDREN: int}21315&{PAYLOAD: dict}id=${1}name=Robotchildren=${CHILDREN}
Variable conversion on command line

Variable conversion works also with thecommand line variables that arecreated using the--variable option. The syntax isname: type:value and,due to the space being mandatory, the whole option value typically needs tobe quoted. Following examples demonstrate some possible usages for thisfunctionality:

--variable "ITERATIONS: int:99"--variable "PAYLOAD: dict:{'id': 1, 'name': 'Robot', 'children': [2, 13, 15]}"--variable "START_TIME: datetime:now"
Failing conversion

If type conversion fails, there is an error and the variable is not created.Conversion fails if the value cannot be converted to the specifiedtype or if the type itself is not supported:

*** Test Cases ***Invalid valueVAR    ${example: int}invalidInvalid typeVAR    ${example: invalid}123

2.6.4   Built-in variables

Robot Framework provides some built-in variables that are availableautomatically.

Operating-system variables

Built-in variables related to the operating system ease making the test dataoperating-system-agnostic.

Available operating-system-related built-in variables
VariableExplanation
${CURDIR}An absolute path to the directory where the test datafile is located. This variable is case-sensitive.
${TEMPDIR}An absolute path to the system temporary directory. In UNIX-likesystems this is typically/tmp, and in Windowsc:\Documents and Settings\<user>\Local Settings\Temp.
${EXECDIR}An absolute path to the directory where test execution wasstarted from.
${/}The system directory path separator./ in UNIX-likesystems and\ in Windows.
${:}The system path element separator.: in UNIX-likesystems and; in Windows.
${\n}The system line separator.\n in UNIX-like systemsand\r\n in Windows.
*** Test Cases ***ExampleCreate Binary File    ${CURDIR}${/}input.dataSome text here${\n}on two linesSet Environment VariableCLASSPATH    ${TEMPDIR}${:}${CURDIR}${/}foo.jar

Number variables

The variable syntax can be used for creating both integers andfloating point numbers, as illustrated in the example below. This isuseful when a keyword expects to get an actual number, and not astring that just looks like a number, as an argument.

*** Test Cases ***Example 1AConnectexample.com80# Connect gets two strings as argumentsExample 1BConnectexample.com    ${80}# Connect gets a string and an integerExample 2Do X    ${3.14}    ${-1e-4}# Do X gets floating point numbers 3.14 and -0.0001

It is possible to create integers also from binary, octal, andhexadecimal values using0b,0o and0x prefixes, respectively.The syntax is case insensitive.

*** Test Cases ***ExampleShould Be Equal    ${0b1011}    ${11}Should Be Equal    ${0o10}      ${8}Should Be Equal    ${0xff}      ${255}Should Be Equal    ${0B1010}    ${0XA}

Boolean and None/null variables

Also Boolean values and PythonNone canbe created using the variable syntax similarly as numbers.

*** Test Cases ***BooleanSet Status    ${true}# Set Status gets Boolean true as an argumentCreate Ysomething   ${false}# Create Y gets a string and Boolean falseNoneDo XYZ    ${None}# Do XYZ gets Python None as an argument

These variables are case-insensitive, so for example${True} and${true}are equivalent. Keywords accepting Boolean values typically do automaticargument conversion and handle string values likeTrue andfalse asexpected. In such cases using the variable syntax is not required.

Space and empty variables

It is possible to create spaces and empty strings using variables${SPACE} and${EMPTY}, respectively. These variables areuseful, for example, when there would otherwise be a need toescapespaces or empty cells with a backslash. If more than one space isneeded, it is possible to use theextended variable syntax like${SPACE * 5}. In the following example,Should BeEqual keyword gets identical arguments, but those using variables areeasier to understand than those using backslashes.

*** Test Cases ***One spaceShould Be Equal    ${SPACE}\ \Four spacesShould Be Equal    ${SPACE * 4}\ \ \ \ \Ten spacesShould Be Equal    ${SPACE * 10}\ \ \ \ \ \ \ \ \ \ \Quoted spaceShould Be Equal"${SPACE}"" "Quoted spacesShould Be Equal"${SPACE * 2}"" \ "EmptyShould Be Equal    ${EMPTY}\

There is also an emptylist variable@{EMPTY} and an emptydictionaryvariable&{EMPTY}. Because they have no content, they basicallyvanish when used somewhere in the test data. They are useful, for example,withtest templates when thetemplate keyword is used withoutarguments or when overriding list or dictionary variables in differentscopes. Modifying the value of@{EMPTY} or&{EMPTY} is not possible.

*** Test Cases ***Template    [Template]Some keyword    @{EMPTY}OverrideSet Global Variable    @{LIST}    @{EMPTY}Set Suite Variable     &{DICT}    &{EMPTY}

Note

${SPACE} represents the ASCII space (\x20) andother spacesshould be specified using theescape sequences like\xA0(NO-BREAK SPACE) and\u3000 (IDEOGRAPHIC SPACE).

Automatic variables

Some automatic variables can also be used in the test data. Thesevariables can have different values during the test execution and someof them are not even available all the time. Altering the value ofthese variables does not affect the original values, but some valuescan be changed dynamically using keywords from theBuiltIn library.

Available automatic variables
VariableExplanationAvailable
${TEST NAME}The name of the current test case.Test case
@{TEST TAGS}Contains the tags of the current test case inalphabetical order. Can be modified dynamically usingSet Tags andRemove Tags keywords.Test case
${TEST DOCUMENTATION}The documentation of the current test case. Can be setdynamically using usingSet Test Documentationkeyword.Test case
${TEST STATUS}The status of the current test case, either PASS orFAIL.Testteardown
${TEST MESSAGE}The message of the current test case.Testteardown
${PREV TEST NAME}The name of the previous test case, or an empty stringif no tests have been executed yet.Everywhere
${PREV TEST STATUS}The status of the previous test case: either PASS,FAIL, or an empty string when no tests have beenexecuted.Everywhere
${PREV TEST MESSAGE}The possible error message of the previous test case.Everywhere
${SUITE NAME}The full name of the current test suite.Everywhere
${SUITE SOURCE}An absolute path to the suite file or directory.Everywhere
${SUITE DOCUMENTATION}The documentation of the current test suite. Can beset dynamically using usingSet SuiteDocumentation keyword.Everywhere
&{SUITE METADATA}The free metadata of the current test suite. Can beset usingSet Suite Metadata keyword.Everywhere
${SUITE STATUS}The status of the current test suite, either PASS orFAIL.Suiteteardown
${SUITE MESSAGE}The full message of the current test suite, includingstatistics.Suiteteardown
${KEYWORD STATUS}The status of the current keyword, either PASS orFAIL.Userkeywordteardown
${KEYWORD MESSAGE}The possible error message of the current keyword.Userkeywordteardown
${LOG LEVEL}Currentlog level.Everywhere
${OUTPUT DIR}An absolute path to theoutput directory asa string.Everywhere
${OUTPUT FILE}An absolute path to theoutput file as a string ora stringNONE if the output file is not created.Everywhere
${LOG FILE}An absolute path to thelog file as a string ora stringNONE if the log file is not created.Everywhere
${REPORT FILE}An absolute path to thereport file as a string ora stringNONE if the report file is not created.Everywhere
${DEBUG FILE}An absolute path to thedebug file as a string ora stringNONE if the debug file is not created.Everywhere
&{OPTIONS}

A dictionary exposing command line options. Thedictionary keys match the command line options andcan be accessed both like${OPTIONS}[key] and${OPTIONS.key}. Available options:

  • ${OPTIONS.exclude} (--exclude)
  • ${OPTIONS.include} (--include)
  • ${OPTIONS.skip} (--skip)
  • ${OPTIONS.skip_on_failure}(--skip-on-failure)
  • ${OPTIONS.console_width}(integer,--console-width)
  • ${OPTIONS.rpa}(boolean,--rpa)

${OPTIONS} itself was added in RF 5.0,${OPTIONS.console_width} in RF 7.1 and${OPTIONS.rpa} in RF 7.3.More options can be exposed later.

Everywhere

Suite related variables${SUITE SOURCE},${SUITE NAME},${SUITE DOCUMENTATION}and&{SUITE METADATA} as well as options related to command line options like${LOG FILE} and&{OPTIONS} are available already when libraries and variablefiles are imported. Possible variables in these automatic variables are not yetresolved at the import time, though.

2.6.5   Variable priorities and scopes

Variables coming from different sources have different priorities andare available in different scopes.

Variable priorities

Variables from the command line

Variablesset on the command line have the highest priority of allvariables that can be set before the actual test execution starts. Theyoverride possible variables created in Variable sections in test casefiles, as well as in resource and variable files imported in thetest data.

Individually set variables (--variable option) override thevariables set usingvariable files (--variablefile option).If you specify same individual variable multiple times, the one specifiedlast will override earlier ones. This allows setting default values forvariables in astart-up script and overriding them from the command line.Notice, though, that if multiple variable files have same variables, theones in the file specified first have the highest priority.

Variable section in a test case file

Variables created using theVariable section in a test case fileare available for all the test cases in that file. These variablesoverride possible variables with same names in imported resource andvariable files.

Variables created in the Variable sections are available in all other sectionsin the file where they are created. This means that they can be used alsoin the Setting section, for example, for importing more variables fromresource and variable files.

Imported resource and variable files

Variables imported from theresource and variable files have thelowest priority of all variables created in the test data.Variables from resource files and variable files have the samepriority. If several resource and/or variable file have samevariables, the ones in the file imported first are taken into use.

If a resource file imports resource files or variable files,variables in its own Variable section have a higher priority thanvariables it imports. All these variables are available for files thatimport this resource file.

Note that variables imported from resource and variable files are notavailable in the Variable section of the file that imports them. Thisis due to the Variable section being processed before the Setting sectionwhere the resource files and variable files are imported.

Variables set during test execution

Variables set during the test execution usingreturn values from keywords,VAR syntax orSet Test/Suite/Global Variable keywordsalways override possible existingvariables in the scope where they are set. In a sense they thushave the highest priority, but on the other hand they do not affectvariables outside the scope they are defined.

Built-in variables

Built-in variables like${TEMPDIR} and${TEST_NAME}have the highest priority of all variables. They cannot be overriddenusing Variable section or from command line, but even they can be reset duringthe test execution. An exception to this rule arenumber variables, whichare resolved dynamically if no variable is found otherwise. They can thus beoverridden, but that is generally a bad idea. Additionally${CURDIR}is special because it is replaced already during the test data processing time.

Variable scopes

Depending on where and how they are created, variables can have aglobal, test suite, test case or local scope.

Global scope

Global variables are available everywhere in the test data. Thesevariables are normallyset from the command line with the--variable and--variablefile options, but it is alsopossible to create new global variables or change the existing onesby using theVAR syntax or theSet Global Variable keyword anywhere inthe test data. Additionally alsobuilt-in variables are global.

It is recommended to use capital letters with all global variables.

Test suite scope

Variables with the test suite scope are available anywhere in thetest suite where they are defined or imported. They can be createdin Variable sections, imported fromresource and variable files,or set during the test execution using theVAR syntax or theSet Suite Variable keyword.

The test suite scopeis not recursive, which means that variablesavailable in a higher-level test suiteare not available inlower-level suites. If necessary,resource and variable files canbe used for sharing variables.

Since these variables can be considered global in the test suite wherethey are used, it is recommended to use capital letters also with them.

Test case scope

Variables with the test case scope are visible in a test case and inall user keywords the test uses. Initially there are no variables inthis scope, but it is possible to create them by using theVAR syntax ortheSet Test Variable keyword anywhere in a test case.

If a variable with the test scope is created in suite setup, the variable isavailable everywhere within that suite setup as well as in the corresponding suiteteardown, but it is not seen by tests or possible child suites. If sucha variable is created in a suite teardown, the variable is available onlyin that teardown.

Also variables in the test case scope are to some extend global. It isthus generally recommended to use capital letters with them too.

Note

Creating variables with the test scope in a suite setup or teardowncaused an error prior to Robot Framework 7.2.

Local scope

Test cases and user keywords have a local variable scope that is notseen by other tests or keywords. Local variables can be created usingreturn values from executed keywords and with theVAR syntax,and user keywords also get them asarguments.

It is recommended to use lower-case letters with local variables.

2.6.6   Advanced variable features

Extended variable syntax

Extended variable syntax allows accessing attributes of an object assignedto a variable (for example,${object.attribute}) and even callingits methods (for example,${obj.get_name()}).

Extended variable syntax is a powerful feature, but it shouldbe used with care. Accessing attributes is normally not a problem, onthe contrary, because one variable containing an object with severalattributes is often better than having several variables. On theother hand, calling methods, especially when they are used witharguments, can make the test data pretty complicated to understand.If that happens, it is recommended to move the code into a library.

The most common usages of extended variable syntax are illustratedin the example below. First assume that we have the followingvariable file and test case:

classMyObject:def__init__(self,name):self.name=namedefeat(self,what):returnf'{self.name} eats{what}'def__str__(self):returnself.nameOBJECT=MyObject('Robot')DICTIONARY={1:'one',2:'two',3:'three'}
*** Test Cases ***ExampleKW 1    ${OBJECT.name}KW 2    ${OBJECT.eat('Cucumber')}KW 3    ${DICTIONARY[2]}

When this test data is executed, the keywords get the arguments asexplained below:

  • KW 1 gets stringRobot
  • KW 2 gets stringRobot eats Cucumber
  • KW 3 gets stringtwo

The extended variable syntax is evaluated in the following order:

  1. The variable is searched using the full variable name. The extendedvariable syntax is evaluated only if no matching variable is found.
  2. The name of the base variable is created. The body of the nameconsists of all the characters after the opening{ untilthe first occurrence of a character that is not an alphanumeric character,an underscore or a space. For example, base variables of${OBJECT.name}and${DICTIONARY[2]}) areOBJECT andDICTIONARY, respectively.
  3. A variable matching the base name is searched. If there is no match, anexception is raised and the test case fails.
  4. The expression inside the curly brackets is evaluated as a Pythonexpression, so that the base variable name is replaced with itsvalue. If the evaluation fails because of an invalid syntax or thatthe queried attribute does not exist, an exception is raised andthe test fails.
  5. The whole extended variable is replaced with the value returnedfrom the evaluation.

Many standard Python objects, including strings and numbers, havemethods that can be used with the extended variable syntax eitherexplicitly or implicitly. Sometimes this can be really useful andreduce the need for setting temporary variables, but it is also easyto overuse it and create really cryptic test data. Following examplesshow few pretty good usages.

*** Test Cases ***StringVAR    ${string}abcLog    ${string.upper()}# Logs 'ABC'Log    ${string * 2}# Logs 'abcabc'NumberVAR    ${number}    ${-2}Log    ${number * 10}# Logs -20Log    ${number.__abs__()}# Logs 2

Note that even thoughabs(number) is recommended overnumber.__abs__() in normal Python code, using${abs(number)} does not work. This is because the variable namemust be in the beginning of the extended syntax. Using__xxx__methods in the test data like this is already a bit questionable, andit is normally better to move this kind of logic into test libraries.

Extended variable syntax works also inlist variable anddictionary variablecontexts. If, for example, an object assigned to a variable${EXTENDED} hasan attributeattribute that contains a list as a value, it can beused as a list variable@{EXTENDED.attribute}.

Extended variable assignment

It is possible to set attributes ofobjects stored to scalar variables usingkeyword return values anda variation of theextended variable syntax. Assuming we havevariable${OBJECT} from the previous examples, attributes couldbe set to it like in the example below.

*** Test Cases ***Example    ${OBJECT.name} =Set VariableNew name    ${OBJECT.new_attr} =Set VariableNew attribute

The extended variable assignment syntax is evaluated using thefollowing rules:

  1. The assigned variable must be a scalar variable and have at leastone dot. Otherwise the extended assignment syntax is not used andthe variable is assigned normally.
  2. If there exists a variable with the full name(e.g.${OBJECT.name} in the example above) that variablewill be assigned a new value and the extended syntax is not used.
  3. The name of the base variable is created. The body of the nameconsists of all the characters between the opening${ andthe last dot, for example,OBJECT in${OBJECT.name}andfoo.bar in${foo.bar.zap}. As the second exampleillustrates, the base name may contain normal extended variablesyntax.
  4. The name of the attribute to set is created by taking all thecharacters between the last dot and the closing}, forexample,name in${OBJECT.name}. If the name does notstart with a letter or underscore and contain only these charactersand numbers, the attribute is considered invalid and the extendedsyntax is not used. A new variable with the full name is createdinstead.
  5. A variable matching the base name is searched. If no variable isfound, the extended syntax is not used and, instead, a new variableis created using the full variable name.
  6. If the found variable is a string or a number, the extended syntaxis ignored and a new variable created using the full name. This isdone because you cannot add new attributes to Python strings ornumbers, and this way the syntax is also less backwards-incompatible.
  7. If all the previous rules match, the attribute is set to the basevariable. If setting fails for any reason, an exception is raisedand the test fails.

Note

Unlike when assigning variables normally usingreturnvalues from keywords, changes to variables done using theextended assign syntax are not limited to the currentscope. Because no new variable is created but instead thestate of an existing variable is changed, all tests andkeywords that see that variable will also see the changes.

Variables inside variables

Variables are allowed also inside variables, and when this syntax isused, variables are resolved from the inside out. For example, if youhave a variable${var${x}}, then${x} is resolvedfirst. If it has the valuename, the final value is then thevalue of the variable${varname}. There can be several nestedvariables, but resolving the outermost fails, if any of them does notexist.

In the example below,Do X gets the value${JOHN HOME}or${JANE HOME}, depending on ifGet Name returnsjohn orjane. If it returns something else, resolving${${name} HOME} fails.

*** Variables ***${JOHN HOME}/home/john${JANE HOME}/home/jane*** Test Cases ***Example    ${name} =Get NameDo X    ${${name} HOME}

Inline Python evaluation

Variable syntax can also be used for evaluating Python expressions. Thebasic syntax is${{expression}} i.e. there are double curly braces aroundthe expression. Theexpression can be any valid Python expression such as${{1 + 2}} or${{['a', 'list']}}. Spaces around the expression are allowed,so also${{ 1 + 2 }} and${{ ['a', 'list'] }} are valid. In addition tousing normalscalar variables, alsolist variables anddictionary variables support@{{expression}} and&{{expression}} syntax,respectively.

Main usages for this pretty advanced functionality are:

  • Evaluating Python expressions involving Robot Framework's variables(${{len('${var}') > 3}},${{$var[0] if $var is not None else None}}).
  • Creating values that are not Python base types(${{decimal.Decimal('0.11')}},${{datetime.date(2019, 11, 5)}}).
  • Creating values dynamically (${{random.randint(0, 100)}},${{datetime.date.today()}}).
  • Constructing collections, especially nested collections (${{[1, 2, 3, 4]}},${{ {'id': 1, 'name': 'Example', 'children': [7, 9]} }}).
  • Accessing constants and other useful attributes in Python modules(${{math.pi}},${{platform.system()}}).

This is somewhat similar functionality than theextended variable syntaxdiscussed earlier. As the examples above illustrate, this syntax is even morepowerful as it provides access to Python built-ins likelen() and moduleslikemath. In addition to being able to use variables like${var} inthe expressions (they are replaced before evaluation), variables are alsoavailable using the special$var syntax during evaluation. The whole expressionsyntax is explained in theEvaluating expressions appendix.

Tip

Instead of creating complicated expressions, it is often betterto move the logic into acustom library. That easesmaintenance, makes test data easier to understand and can alsoenhance execution speed.

Note

The inline Python evaluation syntax is new in Robot Framework 3.2.

2.7   Creating user keywords

Keyword sections are used to create new higher-level keywords bycombining existing keywords together. These keywords are calleduserkeywords to differentiate them from lowest levellibrary keywordsthat are implemented in test libraries. The syntax for creating userkeywords is very close to the syntax for creating test cases, whichmakes it easy to learn.

2.7.1   User keyword syntax

Basic syntax

In many ways, the overall user keyword syntax is identical to thetest case syntax. User keywords are created in Keyword sectionswhich differ from Test Case sections only by the name that is used toidentify them. User keyword names are in the first column similarly astest cases names. Also user keywords are created from keywords, eitherfrom keywords in test libraries or other user keywords. Keyword namesare normally in the second column, but when setting variables fromkeyword return values, they are in the subsequent columns.

*** Keywords ***Open Login PageOpen Browserhttp://host/login.htmlTitle Should BeLogin PageTitle Should Start With    [Arguments]    ${expected}    ${title} =Get TitleShould Start With    ${title}    ${expected}

Most user keywords take some arguments. This important feature is usedalready in the second example above, and it is explained in detaillater in this section, similarly asuser keyword returnvalues.

User keywords can be created insuite files,resource files,andsuite initialization files. Keywords created in resourcefiles are available for files using them, whereas other keywords areonly available in the files where they are created.

Settings in the Keyword section

User keywords can have similar settings astest cases, and theyhave the same square bracket syntax separating them from keywordnames. All available settings are listed below and explained later inthis section.

[Documentation]
Used for setting auser keyword documentation.
[Tags]
Setstags for the keyword.
[Arguments]
Specifiesuser keyword arguments.
[Setup],[Teardown]
Specifyuser keyword setup and teardown.[Setup] is new inRobot Framework 7.0.
[Timeout]
Sets the possibleuser keyword timeout.Timeouts are discussedin a section of their own.
[Return]
Specifiesuser keyword return values. Deprecated in Robot Framework 7.0,theRETURN statement should be used instead.

Note

The format used above is recommended, but setting names arecase-insensitive and spaces are allowed between brackets and the name.For example,[ TAGS ]:setting is valid.

2.7.2   User keyword name and documentation

The user keyword name is defined in the first column of theKeyword section. Of course, the name should be descriptive, and it isacceptable to have quite long keyword names. Actually, when creatinguse-case-like test cases, the highest-level keywords are oftenformulated as sentences or even paragraphs.

User keywords can have a documentation that is set with the[Documentation] setting. It supports same formatting,splitting to multiple lines, and other features astest case documentation.This setting documents the user keyword in the test data. It is also shownin a more formal keyword documentation, which theLibdoc tool can createfromresource files. Finally, the first logical row of the documentation,until the first empty row, is shown as a keyword documentation intest logs.

*** Keywords ***One line documentation    [Documentation]One line documentation.No OperationMultiline documentation    [Documentation]The first line creates the short doc.    ...    ...This is the body of the documentation.    ...It is not shown in Libdoc outputs but only    ...the short doc is shown in logs.No OperationShort documentation in multiple lines    [Documentation]If the short doc gets longer, it can span    ...multiple physical lines.    ...    ...The body is separated from the short doc with    ...an empty line.No Operation

Sometimes keywords need to be removed, replaced with new ones, ordeprecated for other reasons. User keywords can be marked deprecatedby starting the documentation with*DEPRECATED*, which willcause a warning when the keyword is used. For more information, seetheDeprecating keywords section.

Note

Prior to Robot Framework 3.1, the short documentation containedonly the first physical line of the keyword documentation.

2.7.3   User keyword tags

Both user keywords andlibrary keywords can have tags. Similarly as whentagging test cases, there are two settings affecting user keyword tags:

Keyword Tags setting in the Settings section
All keywords in a file with this setting always get specified tags.
[Tags] setting with each keyword
Keywords get these tags in addition to possible tags specified using theKeyword Tags setting. The[Tags] setting also allowsremoving tags set withKeyword Tags by using the-tag syntax.
*** Settings ***Keyword Tagsguihtml*** Keywords ***No own tags    [Documentation]Keyword has tags 'gui' and 'html'.No OperationOwn tags    [Documentation]Keyword has tags 'gui', 'html', 'own' and 'tags'.    [Tags]owntagsNo OperationRemove common tag    [Documentation]Test has tags 'gui' and 'own'.    [Tags]own-htmlNo Operation

Keyword tags can be specified using variables, the-tag syntax supportspatterns, and so on, exactly astest case tags.

In addition to using the dedicated settings, keyword tags can be specified onthe last line of the documentation withTags: prefix so that tags are separatedwith a comma. For example, following two keywords get same three tags:

*** Keywords ***Settings tags using separate setting    [Tags]myfinetagsNo OperationSettings tags using documentation    [Documentation]I have documentation. And my documentation has tags.    ...Tags: my, fine, tagsNo Operation

Keyword tags are shown in logs and in documentation generated byLibdoc,where the keywords can also be searched based on tags. The--removekeywordsand--flattenkeywords commandline options also support selecting keywords bytag, and new usages for keywords tags are possibly added in later releases.

Similarly as withtest case tags, user keyword tags with therobot:prefix arereserved for special features by Robot Frameworkitself. Users should thus not use any tag with these prefixes unless actuallyactivating the special functionality. Starting from Robot Framework 6.1,flattening keyword during execution time can be taken into use usingreserved tagrobot:flatten.

Note

Keyword Tags is new in Robot Framework 6.0. With earlierversions all keyword tags need to be specified using the[Tags] setting.

Note

The-tag syntax for removing common tags is new in Robot Framework 7.0.

2.7.4   User keyword arguments

Most user keywords need to take some arguments. The syntax forspecifying them is probably the most complicated feature normallyneeded with Robot Framework, but even that is relatively easy,particularly in most common cases. Arguments are normally specified withthe[Arguments] setting, and argument names use the samesyntax asvariables, for example${arg}.

Positional arguments with user keywords

The simplest way to specify arguments (apart from not having them at all)is using only positional arguments. In most cases, this is allthat is needed.

The syntax is such that first the[Arguments] setting isgiven and then argument names are defined in the subsequentcells. Each argument is in its own cell, using the same syntax as withvariables. The keyword must be used with as many arguments as thereare argument names in its signature. The actual argument names do notmatter to the framework, but from users' perspective they shouldbe as descriptive as possible. It is recommendedto use lower-case letters in variable names, either as${my_arg},${my arg} or${myArg}.

*** Keywords ***One Argument    [Arguments]    ${arg_name}LogGot argument${arg_name}Three Arguments    [Arguments]    ${arg1}    ${arg2}    ${arg3}Log1st argument:${arg1}Log2nd argument:${arg2}Log3rd argument:${arg3}

Default values with user keywords

When creating user keywords, positional arguments are sufficient inmost situations. It is, however, sometimes useful that keywords havedefault values for some or all of their arguments. Also user keywordssupport default values, and the needed new syntax does not add very muchto the already discussed basic syntax.

In short, default values are added to arguments, so that first there isthe equals sign (=) and then the value, for example${arg}=default.There can be many arguments with defaults, but they all must be given afterthe normal positional arguments. The default value can contain avariablecreated ontest, suite or global scope, but local variables of the keywordexecutor cannot be used. Default value canalso be defined based on earlier arguments accepted by the keyword.

Note

The syntax for default values is space sensitive. Spacesbefore the= sign are not allowed, and possible spacesafter it are considered part of the default value itself.

*** Keywords ***One Argument With Default Value    [Arguments]    ${arg}=default value    [Documentation]This keyword takes 0-1 argumentsLogGot argument${arg}Two Arguments With Defaults    [Arguments]    ${arg1}=default 1    ${arg2}=${VARIABLE}    [Documentation]This keyword takes 0-2 argumentsLog1st argument${arg1}Log2nd argument${arg2}One Required And One With Default    [Arguments]    ${required}    ${optional}=default    [Documentation]This keyword takes 1-2 argumentsLogRequired:${required}LogOptional:${optional} Default Based On Earlier Argument    [Arguments]    ${a}    ${b}=${a}    ${c}=${a} and${b}Should Be Equal    ${a}    ${b}Should Be Equal    ${c}    ${a} and${b}

When a keyword accepts several arguments with default values and onlysome of them needs to be overridden, it is often handy to use thenamed arguments syntax. When this syntax is used with userkeywords, the arguments are specified without the${}decoration. For example, the second keyword above could be used likebelow and${arg1} would still get its default value.

*** Test Cases ***ExampleTwo Arguments With Defaultsarg2=new value

As all Pythonistas must have already noticed, the syntax forspecifying default arguments is heavily inspired by Python syntax forfunction default values.

Variable number of arguments with user keywords

Sometimes even default values are not enough and there is a needfor a keyword acceptingvariable number of arguments. User keywordssupport also this feature. All that is needed is havinglist variable suchas@{varargs} after possible positional arguments in the keyword signature.This syntax can be combined with the previously described default values, andat the end the list variable gets all the leftover arguments that do not matchother arguments. The list variable can thus have any number of items, even zero.

*** Keywords ***Any Number Of Arguments    [Arguments]    @{varargs}Log Many    @{varargs}One Or More Arguments    [Arguments]    ${required}    @{rest}Log Many    ${required}    @{rest}Required, Default, Varargs    [Arguments]    ${req}    ${opt}=42    @{others}LogRequired:${req}LogOptional:${opt}LogOthers:FOR    ${item}IN    @{others}Log    ${item}END

Notice that if the last keyword above is used with more than oneargument, the second argument${opt} always gets the givenvalue instead of the default value. This happens even if the givenvalue is empty. The last example also illustrates how a variablenumber of arguments accepted by a user keyword can be used in aforloop. This combination of two rather advanced functions cansometimes be very useful.

The keywords in the examples above could be used, for example, like this:

*** Test Cases ***Varargs with user keywordsAny Number Of ArgumentsAny Number Of ArgumentsargAny Number Of Argumentsarg1arg2arg3arg4One Or More ArgumentsrequiredOne Or More Argumentsarg1arg2arg3arg4Required, Default, VarargsrequiredRequired, Default, VarargsrequiredoptionalRequired, Default, Varargsarg1arg2arg3arg4arg5

Again, Pythonistas probably notice that the variable number ofarguments syntax is very close to the one in Python.

Free named arguments with user keywords

User keywords can also acceptfree named arguments by having adictionaryvariable like&{named} as the absolutely last argument. When the keywordis called, this variable will get allnamed arguments that do not matchanypositional argument ornamed-only argument in the keywordsignature.

*** Keywords ***Free Named Only    [Arguments]    &{named}Log Many    &{named}Positional And Free Named    [Arguments]    ${required}    &{extra}Log Many    ${required}    &{extra}Run Program    [Arguments]    @{args}    &{config}Run Processprogram.py    @{args}    &{config}

The last example above shows how to create a wrapper keyword thataccepts any positional or named argument and passes them forward.Seefree named argument examples for a full example with same keyword.

Free named arguments support with user keywords works similarly as kwargswork in Python. In the signature and also when passing arguments forward,&{kwargs} is pretty much the same as Python's**kwargs.

Named-only arguments with user keywords

Starting from Robot Framework 3.1, user keywords supportnamed-onlyarguments that are inspired byPython 3 keyword-only arguments.This syntax is typically used by having normal argumentsaftervariable number of arguments (@{varargs}). If the keywords does notuse varargs, it is possible to use just@{} to denote that the subsequentarguments are named-only:

*** Keywords ***With Varargs    [Arguments]    @{varargs}    ${named}Log Many    @{varargs}    ${named}Without Varargs    [Arguments]    @{}    ${first}    ${second}Log Many    ${first}    ${second}

Named-only arguments can be used together withpositional arguments aswell as withfree named arguments. When using free named arguments, theymust be last:

*** Keywords ***With Positional    [Arguments]    ${positional}    @{}    ${named}Log Many    ${positional}    ${named}With Free Named    [Arguments]    @{varargs}    ${named only}    &{free named}Log Many    @{varargs}    ${named only}    &{free named}

When passing named-only arguments to keywords, their order does not matterother than they must follow possible positional arguments. The keywords abovecould be used, for example, like this:

*** Test Cases ***ExampleWith Varargsnamed=valueWith Varargspositionalsecond positionalnamed=foobarWithout Varargsfirst=1second=2Without Varargssecond=tokafirst=ekaWith Positionalfoonamed=barWith Positionalnamed=2positional=1With Free Namedpositionalnamed only=valuex=1y=2With Free Namedfoo=abar=bnamed only=cquux=d

Named-only arguments can have default values similarly asnormal userkeyword arguments. A minor difference is that the order of argumentswith and without default values is not important.

*** Keywords ***With Default    [Arguments]    @{}    ${named}=defaultLog Many    ${named}With And Without Defaults    [Arguments]    @{}    ${optional}=default    ${mandatory}    ${mandatory 2}    ${optional 2}=default 2    ${mandatory 3}Log Many    ${optional}    ${mandatory}    ${mandatory 2}    ${optional 2}    ${mandatory 3}

Argument conversion with user keywords

User keywords support automatic argument conversion based on explicitly specifiedtypes. The type syntax${name: type} is the same, and the supported conversionsare the same, as whencreating variables.

The basic usage with normal arguments is very simple. You only need to specifythe type like${count: int} and the used value is converted automatically.If an argument has a default value like${count: int}=1, also the defaultvalue will be converted. If conversion fails, calling the keyword fails withan informative error message.

*** Test Cases ***Move aroundMove3TurnLEFTMove2.3log=TrueTurnrightFailing moveMovebadFailing turnTurnoops*** Keywords ***Move    [Arguments]    ${distance: float}    ${log: bool}=FalseIF    ${log}LogMoving${distance} meters.END Turn    [Arguments]    ${direction: Literal["LEFT", "RIGHT"]}LogTurning${direction}.

Tip

UsingLiteral, like in the above example, is a convenient way tolimit what values are accepted.

When usingvariable number of arguments, the type is specified like@{numbers: int} and is applied to all arguments. If arguments may havedifferent types, it is possible to use an union like@{numbers: float | int}.Withfree named arguments the type is specified like&{named: int} andit is applied to all argument values. Converting argument names is not supported.

*** Test Cases ***VarargsSend bytesHello!Hyvä!\x00\x00\x07Free namedLog releasesrc 1=2025-05-08rc 2=2025-05-19rc 3=2025-05-21final=2025-05-30*** Keywords ***Send bytes    [Arguments]    @{data: bytes}FOR    ${value}IN    @{data}Log    ${value}formatter=reprENDLog releases    [Arguments]    &{releases: date}FOR    ${version}    ${date}IN    &{releases}LogRF 7.3${version} was released on${date.day}.${date.month}.${date.year}.END

Note

Argument conversion with user keywords is new in Robot Framework 7.3.

2.7.5   Embedding arguments into keyword name

The previous section explained how to pass arguments to keywords sothat they are listed separately after the keyword name. RobotFramework has also another approach to pass arguments, embedding themdirectly to the keyword name, used by the second test below:

*** Test Cases ***Normal argumentsSelect from listcatEmbedded argumentsSelect cat from list

As the example illustrates, embedding arguments to keyword namescan make the data easier to read and understand even for people withoutany Robot Framework experience.

Basic syntax

The previous example showed how using a keywordSelect cat from list ismore fluent than usingSelect from list so thatcat is passed toit as an argument. We obviously could implementSelect cat from listas a normal keyword accepting no arguments, but then we needed to implementvarious other keywords likeSelect dog from list for other animals.Embedded arguments simplify this and we can instead implement just onekeyword with nameSelect ${animal} from list and use it with anyanimal:

*** Test Cases ***Embedded argumentsSelect cat from listSelect dog from list*** Keywords ***Select${animal} from listOpen PagePet SelectionSelect Item From Listanimal_list    ${animal}

As the above example shows, embedded arguments are specified simply by usingvariables in keyword names. The arguments used in the name are naturallyavailable inside the keyword and they have different values depending on howthe keyword is called. In the above example,${animal} has valuecat whenthe keyword is used for the first time anddog when it is used forthe second time.

Starting from Robot Framework 6.1, it is possible to create user keywordsthat accept both embedded and "normal" arguments:

*** Test Cases ***Embedded and normal argumentsNumber of cats should be2Number of dogs should becount=3*** Keywords ***Number of${animals} should be    [Arguments]    ${count}Open PagePet SelectionSelect Items From Listanimal_list    ${animals}Number of Selected List Items Should Be    ${count}

Other than the special name, keywords with embeddedarguments are created just like other user keywords. They are also used the sameway as other keywords except that spaces and underscores are not ignored in theirnames when keywords are matched. They are, however, case-insensitive likeother keywords. For example, theSelect ${animal} from list keyword couldbe used likeselect cow from list, but not likeSelect cow fromlist.

Embedded arguments do not support default values or variable number ofarguments like normal arguments do. If such functionality is needed, normalarguments should be used instead. Passing embedded arguments as variablesis possible, but that can reduce readability:

*** Variables ***${SELECT}cat*** Test Cases ***Embedded arguments with variableSelect${SELECT} from list*** Keywords ***Select${animal} from listOpen PagePet SelectionSelect Item From Listanimal_list    ${animal}

Embedded arguments matching wrong values

One tricky part in using embedded arguments is making sure that thevalues used when calling the keyword match the correct arguments. Thisis a problem especially if there are multiple arguments and charactersseparating them may also appear in the given values. For example,Select Los Angeles Lakers in the following example matchesSelect ${city} ${team} so that${city} containsLos and${team} containsAngeles Lakers:

*** Test Cases ***ExampleSelect Chicago BullsSelect Los Angeles Lakers*** Keywords ***Select${city}${team}LogSelected${team} from${city}.

An easy solution to this problem is surrounding arguments with double quotes orother characters not used in the actual values. This fixed example works sothat cities and teams match correctly:

*** Test Cases ***ExampleSelect "Chicago" "Bulls"Select "Los Angeles" "Lakers"*** Keywords ***Select "${city}" "${team}"LogSelected${team} from${city}.

This approach is not enough to resolve all conflicts, but it helps in commoncases and is generally recommended. Another benefit is that it makes argumentsstand out from rest of the keyword.

Prior to Robot Framework 7.1, embedded arguments starting the keyword name alsomatched possiblegiven/when/then/and/but prefixes typically used in BehaviorDriven Development (BDD). For example,${name} goes home matchedGiven Janne goes home so that${name} got valueGiven Janne.Nowadays the prefix is ignored and${name} will beJanne as expected.If older Robot Framework versions need to be supported, it is easiest to quotethe argument like in"${name}" goes home to get consistent behavior.

An alternative solution for limiting what values arguments match isusing custom regular expressions.

Resolving conflicts

When using embedded arguments, it is pretty common that there are multiplekeyword implementations that match the keyword that is used. For example,Execute "ls" with "lf" in the example below matches both of the keywords.It matchingExecute "${cmd}" with "${opts}" is pretty obvious and whatwe want, but it also matchesExecute "${cmd}" so that${cmd} matchesls" with "-lh.

*** Settings ***LibraryProcess*** Test Cases ***Automatic conflict resolutionExecute "ls"Execute "ls" with "-lh"*** Keywords ***Execute "${cmd}"Run Process    ${cmd}shell=TrueExecute "${cmd}" with "${opts}"Run Process    ${cmd}${opts}shell=True

When this kind of conflicts occur, Robot Framework tries to automatically selectthe best match and use that. In the above example,Execute "${cmd}" with "${opts}"is considered a better match than the more genericExecute "${cmd}" andrunning the example thus succeeds without conflicts.

It is not always possible to find a single match that is better than others.For example, the second test below fails becauseRobot Framework matchesboth of the keywords equally well. This kind of conflicts need to be resolvedmanually either by renaming keywords or byusing custom regular expressions.

*** Test Cases ***No conflictAutomation frameworkRobot uprisingUnresolvable conflictRobot Framework*** Keywords ***${type} FrameworkShould Be Equal    ${type}AutomationRobot${action}Should Be Equal    ${action}uprising

Keywords that accept only "normal" arguments or no arguments at all areconsidered to match better than keywords accepting embedded arguments.For example, if the following keyword is added to the above example,Robot Framework used by the latter test matches it and the testsucceeds:

*** Keywords ***Robot FrameworkNo Operation

Before looking which match is best, Robot Framework checks are some of the matchingkeywords implemented in the same file as the caller keyword. If there are such keywords,they are given precedence over other keywords. Alternatively,library search ordercan be used to control the order in which Robot Framework looks for keywords in resourcesand libraries.

Note

Automatically resolving conflicts if multiple keywords with embeddedarguments match is a new feature in Robot Framework 6.0. With olderversions custom regular expressions explained below can be used instead.

Using custom regular expressions

When keywords with embedded arguments are called, the values are matchedinternally usingregular expressions (regexps for short). The defaultlogic goes so that every argument in the name is replaced with a pattern.*?that matches any string and tries to match as little as possible. This logic worksfairly well normally, but as discussed above, sometimes keywordsmatch wrong values and sometimes there areconflicts that cannotbe resolved . A solution in these cases is specifying a custom regularexpression that makes sure that the keyword matches only what it should in thatparticular context. To be able to use this feature, and to fullyunderstand the examples in this section, you need to understand atleast the basics of the regular expression syntax.

A custom embedded argument regular expression is defined after thebase name of the argument so that the argument and the regexp areseparated with a colon. For example, an argument that should matchonly numbers can be defined like${arg:\d+}.If needed, custom patterns can be prefixed withinline flags such as(?i) for case-insensitivity.

Using custom regular expressions is illustrated by the following examples.The first one shows how the earlier problem withSelect ${city} ${team}not matchingSelect Los Angeles Lakers properly can be resolved withoutquoting by implementing the keyword so that${team} can only contain non-whitespacecharacters.

*** Test Cases ***Do not match whitespace charactersSelect Chicago BullsSelect Los Angeles LakersMatch numbers and characters from set1 + 2 = 353 - 11 = 42Match either date or literal 'today'Deadline is 2022-09-21Deadline is todayCase-insensitive matchSelect dogSelect CAT*** Keywords ***Select${city}${team:\S+}LogSelected${team} from${city}.${number1:\d+}${operator:[+-]}${number2:\d+} =${expected:\d+}    ${result} =Evaluate    ${number1}${operator}${number2}Should Be Equal As Integers    ${result}    ${expected}Deadline is${deadline: date:\d{4}-\d{2}-\d{2}|today}# The ': date' part of the above argument specifies the argument type.# See the separate section about argument conversion for more information.LogDeadline is${deadline.day}.${deadline.month}.${deadline.year}.Select${animal:(?i)cat|dog}    [Documentation]Inline flag `(?i)` makes the pattern case-insensitive.LogSelected${animal}!

Note

Support for inline flags is new in Robot Framework 7.2.

Supported regular expression syntax

Being implemented with Python, Robot Framework naturally uses Python'sre module that has pretty standard regular expressions syntax.This syntax is otherwise fully supported with embedded arguments, butregexp extensions in format(?...) cannot be used. If the regularexpression syntax is invalid, creating the keyword fails with an errorvisible intest execution errors.

Escaping special characters

Regular expressions use the backslash character (\) heavily bothto form special sequences (e.g.\d) and to escape characters that havea special meaning in regexps (e.g.\$). Typically in Robot Framework databackslash charactersneed to be escaped with another backslash, butthat is not required in this context. If there is a need to have a literalbackslash in the pattern, then the backslash must be escaped like${path:c:\\temp\\.*}.

Possible lone opening and closing curly braces in the pattern must be escapedlike${open:\{} and${close:\}} or otherwise Robot Framework is not ableto parse the variable syntax correctly. If there are matching braces like in${digits:\d{2}}, escaping is not needed.

Note

Prior to Robot Framework 3.2, it was mandatory to escape allclosing curly braces in the pattern like${digits:\d{2\}}.This syntax is unfortunately not supported by Robot Framework 3.2or newer and keywords using it must be updated when upgrading.

Note

Prior to Robot Framework 6.0, using literal backslashes in the patternrequired double escaping them like${path:c:\\\\temp\\\\.*}.Patterns using literal backslashes need to be updated when upgrading.

Using variables with custom embedded argument regular expressions

When using embedded arguments with custom regular expressions, specifyingvalues using variables works only if variables match the whole embeddedargument, not if there is any additional content with the variable.For example, the first test below succeeds because the variable${DATE}is used on its own, but the last test fails because${YEAR}-${MONTH}-${DAY}is not a single variable.

*** Variables ***${DATE}2011-06-27${YEAR}2011${MONTH}06${DAY}27*** Test Cases ***SucceedsDeadline is${DATE}Succeeds without variablesDeadline is 2011-06-27FailsDeadline is${YEAR}-${MONTH}-${DAY}*** Keywords ***Deadline is${deadline:\d{4}-\d{2}-\d{2}}Should Be Equal    ${deadline}2011-06-27

Another limitation of using variables is that their actual values are not matchedagainst custom regular expressions. As the result keywords may be called withvalues that their custom regexps would not allow. This behavior is deprecatedstarting from Robot Framework 6.0 and values will be validated in the future.For more information see issue#4462.

Argument conversion with embedded arguments

User keywords accepting embedded arguments support argument conversion with typesyntax${name: type} similarly asnormal user keywords. If acustom patternis needed, it can be separated with an additional colon like${name: type:pattern}.

*** Test Cases ***ExampleBuy 3 booksDeadline is 2025-05-30*** Keywords ***Buy${quantity: int} booksShould Be Equal    ${quantity}    ${3}Deadline is${deadline: date:\d{4}-\d{2}-\d{2}}Should Be Equal    ${deadline.year}     ${2025}Should Be Equal    ${deadline.month}    ${5}Should Be Equal    ${deadline.day}      ${30}

Because the type separator is a colon followed by a space (e.g.${arg: int})and the pattern separator is just a colon (e.g.${arg:\d+}), there typicallyare no conflicts when using only a type or only a pattern. The only exceptionis using a pattern starting with a space, but in that case the space can beescaped like${arg:\ abc} or a type added like${arg: str: abc}.

Note

Argument conversion with user keywords is new in Robot Framework 7.3.

Behavior-driven development example

A big benefit of having arguments as part of the keyword name is that itmakes it easier to use higher-level sentence-like keywords when using thebehavior-driven style to write tests. As the example below shows, thissupport is typically used in combination with the possibility toomit Given, When and Then prefixes in keyword definitions:

*** Test Cases ***Add two numbersGivenI have Calculator openWhenI add 2 and 40Thenresult should be 42Add negative numbersGivenI have Calculator openWhenI add 1 and -2Thenresult should be -1*** Keywords ***I have${program} openStart Program    ${program}I add${number 1} and${number 2}Input Number    ${number 1}Push Button+Input Number    ${number 2}Push Button=Result should be${expected}    ${result} =Get ResultShould Be Equal    ${result}    ${expected}

Note

Embedded arguments feature in Robot Framework is inspired byhowstep definitions are created in the popular BDD toolCucumber.

2.7.6   User keyword return values

Similarly as library keywords, also user keywords can return values.When using Robot Framework 5.0 or newer, the recommended approach isusing the nativeRETURN statement. The old[Return]setting was deprecated in Robot Framework 7.0 and alsoBuiltIn keywordsReturn From Keyword andReturn From Keyword If are considereddeprecated.

Regardless how values are returned, they can beassigned to variablesin test cases and in other user keywords.

UsingRETURN statement

The recommended approach to return values is using theRETURN statement.It accepts optional return values and can be used withIF andinline IFstructures. Its usage is easiest explained with examples:

*** Keywords ***Return One Value    [Arguments]    ${arg}    [Documentation]Return a value unconditionally.    ...Notice that keywords after RETURN are not executed.    ${value} =Convert To Upper Case    ${arg}RETURN    ${value}FailNot executedReturn Three Values    [Documentation]Return multiple values.RETURNabcConditional Return    [Arguments]    ${arg}    [Documentation]Return conditionally.LogBeforeIF    ${arg} == 1LogReturning!RETURNENDLogAfterFind Index    [Arguments]    ${test}    ${items}    [Documentation]Advanced example involving FOR loop, inline IF and@{list} variable syntax.FOR    ${index}    ${item}IN ENUMERATE    @{items}IF$item == $testRETURN    ${index}ENDRETURN    ${-1}

If you want to test the above examples yourself, you can use them with these test cases:

*** Settings ***LibraryString*** Test Cases ***One return value    ${ret} =Return One ValueargumentShould Be Equal    ${ret}ARGUMENTMultiple return values    ${a}    ${b}    ${c} =Return Three ValuesShould Be Equal    ${a},${b},${c}a, b, cConditional returnConditional Return1Conditional Return2Advanced    @{list} =Create Listfoobarbaz    ${index} =Find Indexbar    ${list}Should Be Equal    ${index}    ${1}    ${index} =Find Indexnon existing    ${list}Should Be Equal    ${index}    ${-1}

Note

RETURN syntax is case-sensitive similarly asIF andFOR.

Note

RETURN is new in Robot Framework 5.0. Use approaches explainedbelow if you need to support older versions.

Using[Return] setting

The[Return] setting defines what the keyword should return afterit has been executed. Although it is recommended to have it at the end of keywordwhere it logically belongs, its position does not affect how it is used.

An inherent limitation of the[Return] setting is that cannot be usedconditionally. Thus only the first two earlierRETURN statement examplescan be created using it.

*** Keywords ***Return One Value    [Arguments]    ${arg}    ${value} =Convert To Upper Case    ${arg}    [Return]    ${value}Return Three Values    [Return]abc

Note

The[Return] setting was deprecated in Robot Framework 7.0and theRETURN statement should be used instead. If there is a needto support older Robot Framework versions that do not supportRETURN,it is possible to use the special keywords discussed in the next section.

Using special keywords to return

BuiltIn keywordsReturn From Keyword andReturn From Keyword Ifallow returning from a user keyword conditionally in the middle of the keyword.Both of them also accept optional return values that are handled exactly likewith theRETURN statement and the[Return] setting discussed above.

The introduction of theRETURN statement makes these keywords redundant.Examples below contain same keywords as earlierRETURN examples but theseones are more verbose:

*** Keywords ***Return One Value    [Arguments]    ${arg}    ${value} =Convert To Upper Case    ${arg}Return From Keyword    ${value}FailNot executedReturn Three ValuesReturn From KeywordabcConditional Return    [Arguments]    ${arg}LogBeforeIF    ${arg} == 1LogReturning!Return From KeywordENDLogAfterFind Index    [Arguments]    ${test}    ${items}FOR    ${index}    ${item}IN ENUMERATE    @{items}Return From Keyword If$item == $test    ${index}ENDReturn From Keyword    ${-1}

Note

These keywords are effectively deprecated and theRETURN statement should beused unless there is a need to support also older versions than Robot Framework5.0. There is no visible deprecation warning when using these keywords yet, butthey will be loudly deprecated and eventually removed in the future.

2.7.7   User keyword setup and teardown

A user keyword can have a setup and a teardown similarly astests.They are specified using[Setup] and[Teardown]settings, respectively, directly to the keyword having them. Unlike withtests, it is not possible to specify a common setup or teardown to allkeywords in a certain file.

A setup and a teardown are always a single keyword, but they can themselves beuser keywords executing multiple keywords internally. It is possible to specifythem as variables, and using a specialNONE value (case-insensitive) isthe same as not having a setup or a teardown at all.

User keyword setup is not much different to the first keyword inside the createduser keyword. The only functional difference is that a setup can be specified asa variable, but it can also be useful to be able to explicitly mark a keywordto be a setup.

User keyword teardowns are, exactly as test teardowns, executed also if the userkeyword fails. They are thus very useful when needing to do something at theend of the keyword regardless of its status. To ensure that all cleanup activitiesare done, thecontinue on failure mode is enabled by default with user keywordteardowns the same way as with test teardowns.

*** Keywords ***Setup and teardown    [Setup]LogNew in RF 7!Do Something    [Teardown]LogOld feature.Using variables    [Setup]       ${SETUP}Do Something    [Teardown]    ${TEARDOWN}

Note

User keyword setups are new in Robot Framework 7.0.

2.7.8   Private user keywords

User keywords can betagged with a specialrobot:private tag to indicatethat they should only be used in the file where they are created:

*** Keywords ***Public KeywordPrivate KeywordPrivate Keyword    [Tags]robot:privateNo Operation

Using therobot:private tag does not outright prevent using the keywordoutside the file where it is created, but such usages will cause a warning.If there is both a public and a private keyword with the same name,the public one will be used but also this situation causes a warning.

Private keywords are included in spec files created byLibdoc but not in itsHTML output files.

Note

Private user keywords are new in Robot Framework 6.0.

2.7.9   Recursion

User keywords can call themselves either directly or indirectly. This kind ofrecursive usage is fine as long as the recursion ends, typically based on somecondition, before the recursion limit is exceeded. The limit exists becauseotherwise infinite recursion would crash the execution.

Robot Framework's recursion detection works so, that it checks is the currentrecursion level close to the recursion limit of the underlying Python process.If it is close enough, no more new started keywords or control structures areallowed and execution fails.

Python's default recursion limit is 1000 stack frames, which in practice means thatit is possible to start approximately 140 keywords or control structures.If that is not enough, Python's recursion limit can be raised using thesys.setrecursionlimit() function. As the documentation of the function explains,this should be done with care, because a too-high level can lead to a crash.

Note

Prior to Robot Framework 7.2, the recursion limit was hard-coded to100 started keywords or control structures.

2.8   Resource and variable files

User keywords and variables insuite files andsuiteinitialization files can only be used in files where they arecreated, butresource files provide a mechanism for sharing them.The high level syntax for creating resource files is exactly the sameas when creating suite files andsupported file formats are the sameas well. The main difference is that resource files cannot have tests.

Variable files provide a powerful mechanism for creating and sharingvariables. For example, they allow values other than strings andenable creating variables dynamically. Their flexibility comes fromthe fact that they are created using Python or YAML, whichalso makes them somewhat more complicated thanVariable sections.

2.8.1   Resource files

Resource files are typically created using the plain text format, but alsoreStructuredText format andJSON format are supported.

Taking resource files into use

Resource files are imported using theResource setting in theSettings section so that the path to the resource file is given as an argumentto the setting. The recommended extension for resource files is.resource.For backwards compatibility reasons also.robot,.txt and.tsv work, but using.resource may be mandated in the future.

If the resource file path is absolute, it is used directly. Otherwise,the resource file is first searched relatively to the directorywhere the importing file is located. If the file is not found there,it is then searched from the directories in Python'smodule search path.Searching resource files from the module search path makes it possible tobundle them into Python packages aspackage data and importingthem likepackage/example.resource.

The resource file path can contain variables, and it is recommended to usethem to make paths system-independent (for example,${RESOURCES}/login.resource or just${RESOURCE_PATH}).Additionally, forward slashes (/) in the pathare automatically changed to backslashes (\) on Windows.

*** Settings ***Resourceexample.resourceResource../resources/login.resourceResourcepackage/example.resourceResource    ${RESOURCES}/common.resource

The user keywords and variables defined in a resource file areavailable in the file that takes that resource file intouse. Similarly available are also all keywords and variables from thelibraries, resource files and variable files imported by the saidresource file.

Note

The.resource extension is new in Robot Framework 3.1.

Resource file structure

The higher-level structure of resource files is the same as that ofsuite files otherwise, but they cannot contain tests or tasks.Additionally, the Setting section in resource files can contain only imports(Library,Resource,Variables),Documentation andKeyword Tags.The Variable section and Keyword section are used exactly the same wayas in suite files.

If several resource files have a user keyword with the same name, theymust be used so that thekeyword name is prefixed with the resourcefile name without the extension (for example,myresources.SomeKeyword andcommon.Some Keyword). Moreover, if several resourcefiles contain the same variable, the one that is imported first istaken into use.

Documenting resource files

Keywords created in a resource file can bedocumented using[Documentation] setting. The resource file itself can haveDocumentation in the Setting section similarly assuites.

Libdoc and various editors use these documentations, and theyare naturally available for anyone opening resource files. Thefirst logical line of the documentation of a keyword, until the firstempty line, is logged when the keyword is run, but otherwise resourcefile documentation is ignored during the test execution.

Example resource file

*** Settings ***DocumentationAn example resource fileLibrarySeleniumLibraryResource          ${RESOURCES}/common.resource*** Variables ***${HOST}localhost:7272${LOGIN URL}http://${HOST}/${WELCOME URL}http://${HOST}/welcome.html${BROWSER}Firefox*** Keywords ***Open Login Page    [Documentation]Opens browser to login pageOpen Browser    ${LOGIN URL}    ${BROWSER}Title Should BeLogin PageInput Name    [Arguments]    ${name}Input Textusername_field    ${name}Input Password    [Arguments]    ${password}Input Textpassword_field    ${password}

Resource files using reStructured text format

ThereStructuredText format that can be used withsuite files worksalso with resource files. Such resource files can use either.rstor.rest extension and they are otherwise imported exactly asnormal resource files:

*** Settings ***Resourceexample.rst

When parsing resource files using the reStructuredText format, Robot Frameworkignores all data outside code blocks containing Robot Framework data exactlythe same way as when parsingreStructuredText suite files.For example, the following resource file importsOperatingSystem library,defines${MESSAGE} variable and createsMy Keyword keyword:

Resource file using reStructuredText------------------------------------This text is outside code blocks and thus ignored...code::robotframework*** Settings ***LibraryOperatingSystem*** Variables ***${MESSAGE}Hello, world!Also this text is outside code blocks and ignored. Code blocks notcontaining Robot Framework data are ignored as well...code::robotframework# Both space and pipe separated formats are supported.|*** Keywords ***  |                        |         ||My Keyword        | [Arguments]            | ${path} ||                   |Directory Should Exist | ${path} |

Resource files using JSON format

Resource files can be created usingJSON thesame way as suite files.Such JSON resource files must use either the standard.json extensionor the custom.rsrc extension. They are otherwise imported exactly asnormal resource files:

*** Settings ***Resourceexample.rsrc

Resource files can be converted to JSON usingResourceFile.to_json andrecreated usingResourceFile.from_json:

fromrobot.runningimportResourceFile# Create resource file based on data on the file system.resource=ResourceFile.from_file_system('example.resource')# Save JSON data to a file.resource.to_json('example.rsrc')# Recreate resource from JSON data.resource=ResourceFile.from_json('example.rsrc')

2.8.2   Variable files

Variable files containvariables that can be used in the testdata. Variables can also be created usingVariable sections orset fromthe command line, but variable files allow creating them dynamicallyand also make it easy to create other variable values than strings.

Variable files are typically implemented as modules and there aretwo different approaches for creating variables:

Getting variables directly from a module
Variables are specified as module attributes. In simple cases, thesyntax is so simple that no real programming is needed. For example,MY_VAR = 'my value' creates a variable${MY_VAR} with the specifiedtext as its value. One limitation of this approach is that it doesnot allow using arguments.
Getting variables from a special function
Variable files can have a specialget_variables(orgetVariables) method that returns variables as a mapping.Because the method can take arguments this approach is very flexible.

Alternatively variable files can be implemented asclassesthat the framework will instantiate. Also in this case it is possible to createvariables as attributes or get them dynamically from theget_variablesmethod. Variable files can also be created asYAML andJSON.

Taking variable files into use

Setting section

All test data files can import variable files using theVariablessetting in the Setting section. Variable files are typically imported usinga path to the file same way asresource files are imported usingtheResource setting. Similarly to resource files, the path tothe imported variable file is considered relative to the directory where theimporting file is, and if not found, it is searched from directoriesin themodule search path. The path can also contain variables,and slashes are converted to backslashes on Windows.

Examples:

*** Settings ***Variablesmyvariables.pyVariables../data/variables.pyVariables    ${RESOURCES}/common.yaml

Starting from Robot Framework 5.0, variable files implemented using Pythoncan also be imported using the module namesimilarly as libraries.When using this approach, the module needs to be in themodule search path.

Examples:

*** Settings ***VariablesmyvariablesVariablesrootmodule.Variables

If avariable file accepts arguments, they are specified after the pathor name of the variable file to import:

*** Settings ***Variablesarguments.pyarg1    ${ARG2}Variablesargumentsargument

All variables from a variable file are available in the test data filethat imports it. If several variable files are imported and theycontain a variable with the same name, the one in the earliest imported file istaken into use. Additionally, variables created in Variable sections andset from the command line override variables from variable files.

Command line

Another way to take variable files into use is using the command line option--variablefile. Variable files are referenced using a path ormodule name similarly as when importing them using theVariablessetting. Possible arguments are joined to the path with a colon (:):

--variablefile myvariables.py--variablefile path/variables.py--variablefile /absolute/path/common.py--variablefile variablemodule--variablefile arguments.py:arg1:arg2--variablefile rootmodule.Variables:arg1:arg2

Variable files taken into use from thecommand line are also searched from themodule search path similarly asvariable files imported in the Setting section. Relative paths are consideredrelative to the directory where execution is started from.

If a variable file is given as an absolute Windows path, the colon after thedrive letter is not considered a separator:

--variablefile C:\path\variables.py

It is also possible to use a semicolon(;) as an argument separator. This is useful if variable file argumentsthemselves contain colons, but requires surrounding the whole value withquotes on UNIX-like operating systems:

--variablefile C:\path\variables.py;D:\data.xls--variablefile "myvariables.py;argument:with:colons"

Variables in variable files taken use on the command line are globallyavailable in all test data files, similarly asindividual variablesset with the--variable option. If both--variablefile and--variable options are used and there are variables with samenames, those that are set individually with--variable option take precedence.

Getting variables directly from a module

Basic syntax

When variable files are taken into use, they are imported as Pythonmodules and all their module level attributes that do not start withan underscore (_) are, by default, considered to be variables. Becausevariable names are case-insensitive, both lower- and upper-case names arepossible, but in general, capital letters are recommended for globalvariables and attributes.

VARIABLE="An example string"ANOTHER_VARIABLE="This is pretty easy!"INTEGER=42STRINGS=["one","two","kolme","four"]NUMBERS=[1,INTEGER,3.14]MAPPING={"one":1,"two":2,"three":3}

In the example above, variables${VARIABLE},${ANOTHER VARIABLE}, andso on, are created. The first two variables are strings, the third one isan integer, then there are two lists, and the final value is a dictionary.All these variables can be used as ascalar variable, lists and thedictionary also alist variable like@{STRINGS} (in the dictionary's casethat variable would only contain keys), and the dictionary also as adictionary variable like&{MAPPING}.

To make creating a list variable or a dictionary variable more explicit,it is possible to prefix the variable name withLIST__ orDICT__,respectively:

fromcollectionsimportOrderedDictLIST__ANIMALS=["cat","dog"]DICT__FINNISH=OrderedDict([("cat","kissa"),("dog","koira")])

These prefixes will not be part of the final variable name, but they causeRobot Framework to validate that the value actually is list-like ordictionary-like. With dictionaries the actual stored value is also turnedinto a special dictionary that is used also whencreating dictionariesin the Variable section. Values of these dictionaries are accessibleas attributes like${FINNISH.cat}. These dictionaries are also ordered, butpreserving the source order requires also the original dictionary to beordered.

The variables in both the examples above could be created also using theVariable section below.

*** Variables ***${VARIABLE}An example string${ANOTHER VARIABLE}This is pretty easy!${INTEGER}             ${42}@{STRINGS}onetwokolmefour@{NUMBERS}             ${1}         ${INTEGER}    ${3.14}&{MAPPING}one=${1}two=${2}three=${3}@{ANIMALS}catdog&{FINNISH}cat=kissadog=koira

Note

Variables are not replaced in strings got from variable files.For example,VAR = "an ${example}" would createvariable${VAR} with a literal string valuean ${example} regardless would variable${example}exist or not.

Using objects as values

Variables in variable files are not limited to having only strings orother base types as values like Variable sections. Instead, theirvariables can contain any objects. In the example below, the variable${MAPPING} contains a Python dictionary and also has two variablescreated from a custom object implemented in the same file.

MAPPING={'one':1,'two':2}classMyObject:def__init__(self,name):self.name=nameOBJ1=MyObject('John')OBJ2=MyObject('Jane')
Creating variables dynamically

Because variable files are created using a real programming language,they can have dynamic logic for setting variables.

importosimportrandomimporttimeUSER=os.getlogin()# current login nameRANDOM_INT=random.randint(0,10)# random integer in range [0,10]CURRENT_TIME=time.asctime()# timestamp like 'Thu Apr  6 12:45:21 2006'iftime.localtime()[3]>12:AFTERNOON=Trueelse:AFTERNOON=False

The example above uses standard Python libraries to set differentvariables, but you can use your own code to construct the values. Theexample below illustrates the concept, but similarly, your code couldread the data from a database, from an external file or even ask it fromthe user.

importmathdefget_area(diameter):radius=diameter/2area=math.pi*radius*radiusreturnareaAREA1=get_area(1)AREA2=get_area(2)
Selecting which variables to include

When Robot Framework processes variable files, all their attributesthat do not start with an underscore are expected to bevariables. This means that even functions or classes created in thevariable file or imported from elsewhere are considered variables. Forexample, the last example would contain the variables${math}and${get_area} in addition to${AREA1} and${AREA2}.

Normally the extra variables do not cause problems, but theycould override some other variables and cause hard-to-debugerrors. One possibility to ignore other attributes is prefixing themwith an underscore:

importmathas_mathdef_get_area(diameter):radius=diameter/2.0area=_math.pi*radius*radiusreturnareaAREA1=_get_area(1)AREA2=_get_area(2)

If there is a large number of other attributes, instead of prefixingthem all, it is often easier to use a special attribute__all__ and give it a list of attribute names to be processedas variables.

importmath__all__=['AREA1','AREA2']defget_area(diameter):radius=diameter/2.0area=math.pi*radius*radiusreturnareaAREA1=get_area(1)AREA2=get_area(2)

Note

The__all__ attribute is also, and originally, usedby Python to decide which attributes to importwhen using the syntaxfrom modulename import *.

The third option to select what variables are actually created is usinga specialget_variables function discussed below.

Getting variables from a special function

An alternative approach for getting variables is having a specialget_variables function (also camelCase syntaxgetVariables is possible)in a variable file. If such a function exists, Robot Framework calls it andexpects to receive variables as a Python dictionary with variable names as keysand variable values as values. Created variables canbe used as scalars, lists, and dictionaries exactly like whengettingvariables directly from a module, and it is possible to useLIST__ andDICT__ prefixes to make creating list and dictionary variables more explicit.The example below is functionally identical to the first example related togetting variables directly from a module.

defget_variables():variables={"VARIABLE ":"An example string","ANOTHER VARIABLE":"This is pretty easy!","INTEGER":42,"STRINGS":["one","two","kolme","four"],"NUMBERS":[1,42,3.14],"MAPPING":{"one":1,"two":2,"three":3}}returnvariables

get_variables can also take arguments, which facilitates changingwhat variables actually are created. Arguments to the function are set justas any other arguments for a Python function. Whentaking variable filesinto use, arguments are specified after the pathto the variable file, and in the command line they are separated from thepath with a colon or a semicolon.

The dummy example below shows how to use arguments with variable files. In amore realistic example, the argument could be a path to an external text fileor database where to read variables from.

variables1={'scalar':'Scalar variable','LIST__list':['List','variable']}variables2={'scalar':'Some other value','LIST__list':['Some','other','value'],'extra':'variables1 does not have this at all'}defget_variables(arg):ifarg=='one':returnvariables1else:returnvariables2

Starting from Robot Framework 7.0, arguments to variable files support automaticargument conversion as well as named argument syntax. For example, a variablefile withget_variables(first: int = 0, second: str = '') could be importedlike this:

*** Settings ***Variablesexample.py42# Converted to integer.Variablesexample.pysecond=value# Named argument syntax.

Implementing variable file as a class

It is possible to implement variables files also as a class.

Implementation

Because variable files are always imported using a file system path,the class must have the same name as the module it is located in.

The framework will create an instance of the class using no arguments andvariables will be gotten from the instance. Similarly as with modules,variables can be defined as attributes directlyin the instance or gotten from a specialget_variables method.

When variables are defined directly in an instance, all attributes containingcallable values are ignored to avoid creating variables from possible methodsthe instance has. If you would actually need callable variables, you needto use other approaches to create variable files.

Examples

The first examples create variables from attributes.It creates variables${VARIABLE} and@{LIST} from classattributes and${ANOTHER VARIABLE} from an instance attribute.

classStaticExample:variable='value'LIST__list=[1,2,3]_not_variable='starts with an underscore'def__init__(self):self.another_variable='another value'

The second examples utilizes dynamic approach for getting variables. Itcreates only one variable${DYNAMIC VARIABLE}.

classDynamicExample:defget_variables(self,*args):return{'dynamic variable':' '.join(args)}

Variable file as YAML

Variable files can also be implemented asYAML files.YAML is a data serialization language with a simple and human-friendly syntaxthat is nevertheless easy for machines to parse.The following example demonstrates a simple YAML file:

string:Hello, world!integer:42list:-one-twodict:one:yksitwo:kaksiwith spaces:kolme

YAML variable files can be used exactly like normal variable filesfrom the command line using--variablefile option, in the Settingssection usingVariables setting, and dynamically using theImport Variables keyword. They are automatically recognized by theirextension that must be either.yaml or.yml.If the above YAML file is imported, it will create exactly the same variablesas this Variable section:

*** Variables ***${STRING}Hello, world!${INTEGER}    ${42}@{LIST}onetwo&{DICT}one=yksitwo=kaksiwith spaces=kolme

YAML files used as variable files must always be mappings on the top level.As the above example demonstrates, keys and values in the mapping becomevariable names and values, respectively. Variable values can be any datatypes supported by YAML syntax. If names or values contain non-ASCIIcharacters, YAML variables files must be UTF-8 encoded.

Mappings used as values are automatically converted to special dictionariesthat are used also whencreating dictionaries in the Variable section.Most importantly, values of these dictionaries are accessible as attributeslike${DICT.one}, assuming their names are valid as Python attribute names.If the name contains spaces or is otherwise not a valid attribute name, it isalways possible to access dictionary values using syntax like${DICT}[with spaces] syntax.

Note

Using YAML files with Robot Framework requiresPyYAML module to be installed. You can typicallyinstall it withpip likepip install pyyaml.

Variable file as JSON

Variable files can also be implemented asJSON files.Similarly as YAML discussed in the previous section, JSON is a dataserialization format targeted both for humans and machines. It is based onJavaScript syntax and it is not as human-friendly as YAML, but it stillrelatively easy to understand and modify. The following example containsexactly the same data as the earlier YAML example:

{"string":"Hello, world!","integer":42,"list":["one","two"],"dict":{"one":"yksi","two":"kaksi","with spaces":"kolme"}}

JSON variable files are automatically recognized by their.jsonextension and they can be used exactly like YAML variable files. Theyalso have exactly same requirements for structure, encoding, and so on.Unlike YAML, Python supports JSON out-of-the-box so no extra modules needto be installed.

Note

Support for JSON variable files is new in Robot Framework 6.1.

2.9   Control structures

This section describes various structures that can be used to control the testexecution flow. These structures are familiar from most programming languagesand they allow conditional execution, repeatedly executing a block of keywordsand fine-grained error handling. For readability reasons these structures shouldbe used judiciously, and more complex use cases should be preferablyimplemented intest libraries.

2.9.1   FOR loops

Repeating same actions several times is quite a common need in testautomation. With Robot Framework, test libraries can have any kind ofloop constructs, and most of the time loops should be implemented inthem. Robot Framework also has its ownFOR loop syntax, which isuseful, for example, when there is a need to repeat keywords fromdifferent libraries.

FOR loops can be used with both test cases and user keywords. Except forreally simple cases, user keywords are better, because they hide thecomplexity introduced byFOR loops. The basicFOR loop syntax,FOR item IN sequence, is derived from Python, but similarsyntax is supported also by various other programming languages.

SimpleFOR loop

In a normalFOR loop, one variable is assigned based on a list of values,one value per iteration. The syntax starts withFOR (case-sensitive) asa marker, then the loop variable, then a mandatoryIN (case-sensitive) asa separator, and finally the values to iterate. These values can containvariables, includinglist variables.

The keywords used in theFOR loop are on the following rows and the loopends withEND (case-sensitive) on its own row. Keywords inside the loopdo not need to be indented, but that is highly recommended to make the syntaxeasier to read.

*** Test Cases ***ExampleFOR    ${animal}INcatdogLog    ${animal}Log2nd keywordENDLogOutside loopSecond ExampleFOR    ${var}INonetwo    ${3}four    ${five}    ...kuusi7eightnine    ${last}Log    ${var}END

TheFOR loop inExample above is executed twice, so that firstthe loop variable${animal} has the valuecat and thendog. The loop consists of twoLog keywords. In thesecond example, loop values aresplit into two rows and theloop is run altogether ten times.

It is often convenient to useFOR loops withlist variables. This isillustrated by the example below, where@{ELEMENTS} containsan arbitrarily long list of elements and keywordStart Element isused with all of them one by one.

*** Test Cases ***ExampleFOR    ${element}IN    @{ELEMENTS}Start Element    ${element}END

OldFOR loop syntax

Prior to Robot Framework 3.1, theFOR loop syntax was different than nowadays.The marker to start the loop was:FOR instead ofFOR and loop contents neededto be explicitly marked with a backslash instead of using theEND marker to endthe loop. The first example above would look like this using the old syntax:

*** Test Cases ***Example    :FOR    ${animal}    INcatdog    \Log    ${animal}    \Log2nd keywordLogOutside loop

The old syntax was deprecated in Robot Framework 3.2 and the support for it wasremoved altogether in Robot Framework 4.0.

NestingFOR loops

Starting from Robot Framework 4.0, it is possible to use nestedFOR loopssimply by adding a loop inside another loop:

*** Keywords ***Handle Table    [Arguments]    @{table}FOR    ${row}IN    @{table}FOR    ${cell}IN    @{row}Handle Cell    ${cell}ENDEND

There can be multiple nesting levels and loops can also be combined withother control structures:

*** Test Cases ***Multiple nesting levelsFOR    ${root}INr1r2FOR    ${child}INc1c2c3FOR    ${grandchild}INg1g2Log Many    ${root}    ${child}    ${grandchild}ENDENDFOR    ${sibling}INs1s2s3IF'${sibling}' != 's2'Log Many    ${root}    ${sibling}ENDENDEND

Using several loop variables

It is possible to iterate over multiple values in one iteration by usingmultiple loop variables between theFOR andIN markers. There can beany number of loop variables, but the number of values must be evenlydividable by the number of variables. Each iteration consumes as manyvalues as there are variables.

If there are lot of values to iterate, it is often convenient to organizethem below the loop variables, as in the first loop of the example below:

*** Test Cases ***Multiple loop variablesFOR    ${index}    ${english}    ${finnish}IN    ...1catkissa    ...2dogkoira    ...3horsehevonenAdd Translation    ${english}    ${finnish}    ${index}ENDFOR    ${name}    ${id}IN    @{EMPLOYERS}Create    ${name}    ${id}END

FOR-IN-RANGE loop

AllFOR loops in the previous section iterated over a sequence. That is the mostcommon use case, but sometimes it is convenient to have a loop that is executeda certain number of times. For this purpose Robot Framework has a specialFOR index IN RANGE limit loop syntax that is derived from the similar Pythonidiom using thebuilt-in range() function.

Similarly as otherFOR loops, theFOR-IN-RANGE loop starts withFOR that is followed by a loop variable. In this formatthere can be only one loop variable and it contains the current loopindex. After the variable there must beIN RANGE marker (case-sensitive)that is followed by loop limits.

In the simplest case, only the upper limit of the loop isspecified. In this case, loop indices start from zero and increase by oneuntil, but excluding, the limit. It is also possible to give both thestart and end limits. Then indices start from the start limit, butincrease similarly as in the simple case. Finally, it is possible to givealso the step value that specifies the increment to use. If the stepis negative, it is used as decrement.

It is possible to use simple arithmetic such as addition and subtractionwith the range limits. This is especially useful when the limits arespecified with variables. Start, end and step are typically given asintegers, but using float values is possible as well.

*** Test Cases ***Only upper limit    [Documentation]Loops over values from 0 to 9.FOR    ${index}IN RANGE10Log    ${index}ENDStart and end    [Documentation]Loops over values from 1 to 10.FOR    ${index}IN RANGE111Log    ${index}ENDAlso step given    [Documentation]Loops over values 5, 15, and 25.FOR    ${index}IN RANGE52610Log    ${index}ENDNegative step    [Documentation]Loops over values 13, 3, and -7.FOR    ${index}IN RANGE13-13-10Log    ${index}ENDArithmetic    [Documentation]Arithmetic with variable.FOR    ${index}IN RANGE    ${var} + 1Log    ${index}ENDFloat parameters    [Documentation]Loops over values 3.14, 4.34, and 5.54.FOR    ${index}IN RANGE3.146.091.2Log    ${index}END

FOR-IN-ENUMERATE loop

Sometimes it is useful to loop over a list and also keep track of your locationinside the list. Robot Framework has a specialFOR index ... IN ENUMERATE ... syntax for this situation.This syntax is derived from thePython built-in enumerate() function.

FOR-IN-ENUMERATE loops syntax is just like the regularFOR loop syntax,except that the separator between variables and values isIN ENUMERATE(case-sensitive). Typically they are used so that there is an additional indexvariable before any other loop-variables. By default the index has a value0on the first iteration,1 on the second, and so on.

For example, the following two test cases do the same thing:

*** Variables ***@{LIST}abc*** Test Cases ***Manage index manually    ${index} =Set Variable-1FOR    ${item}IN    @{LIST}        ${index} =Evaluate    ${index} + 1My Keyword    ${index}    ${item}ENDFOR-IN-ENUMERATEFOR    ${index}    ${item}IN ENUMERATE    @{LIST}My Keyword    ${index}    ${item}END

Starting from Robot Framework 4.0, it is possible to specify a custom start indexby usingstart=<index> syntax as the last item of theFOR ... IN ENUMERATE ...header:

*** Variables ***@{LIST}abc${START}10*** Test Cases ***FOR-IN-ENUMERATE with startFOR    ${index}    ${item}IN ENUMERATE    @{LIST}start=1My Keyword    ${index}    ${item}ENDStart as variableFOR    ${index}    ${item}IN ENUMERATE    @{LIST}start=${start}My Keyword    ${index}    ${item}END

Thestart=<index> syntax must be explicitly used in theFOR header and it cannotitself come from a variable. If the last actual item to enumerate would start withstart=, it needs to be escaped likestart\=.

Just like with regularFOR loops, you can loop over multiple values per loopiteration as long as the number of values in your list is evenly divisible bythe number of loop-variables (excluding the index variable):

*** Test Cases ***FOR-IN-ENUMERATE with two values per iterationFOR    ${index}    ${en}    ${fi}IN ENUMERATE    ...catkissa    ...dogkoira    ...horsehevonenLog"${en}" in English is "${fi}" in Finnish (index:${index})END

If you only use one loop variable withFOR-IN-ENUMERATE loops, that variablewill become a Python tuple containing the index and the iterated value:

*** Test Cases ***FOR-IN-ENUMERATE with one loop variableFOR    ${x}IN ENUMERATE    @{LIST}Length Should Be    ${x}2LogIndex is${x}[0] and item is${x}[1].END

Note

FOR-IN-ENUMERATE loops with only one loop variable is a newfeature in Robot Framework 3.2.

FOR-IN-ZIP loop

Some tests build up several related lists, then loop over them together.Robot Framework has a shortcut for this case:FOR ... IN ZIP ..., whichis derived from thePython built-in zip() function.

This may be easiest to show with an example:

*** Variables ***@{NUMBERS}       ${1}    ${2}    ${5}@{NAMES}onetwofive*** Test Cases ***Iterate over two lists manually    ${length}=Get Length    ${NUMBERS}FOR    ${index}IN RANGE    ${length}Log Many    ${NUMBERS}[${index}]    ${NAMES}[${index}]ENDFOR-IN-ZIPFOR    ${number}    ${name}IN ZIP    ${NUMBERS}    ${NAMES}Log Many    ${number}    ${name}END

As the example above illustrates,FOR-IN-ZIP loops require their own customseparatorIN ZIP (case-sensitive) between loop variables and values.Values used withFOR-IN-ZIP loops must be lists or list-like objects.

Items to iterate over must always be given either asscalar variables like${items} or aslist variables like@{lists} that yield the actualiterated lists. The former approach is more common and it was alreadydemonstrated above. The latter approach works like this:

*** Variables ***@{NUMBERS}       ${1}    ${2}    ${5}@{NAMES}onetwofive@{LISTS}         ${NUMBERS}    ${NAMES}*** Test Cases ***FOR-IN-ZIP with lists from variableFOR    ${number}    ${name}IN ZIP    @{LISTS}Log Many    ${number}    ${name}END

The number of lists to iterate over is not limited, but it must matchthe number of loop variables. Alternatively, there can be just one loopvariable that then becomes a Python tuple getting items from all lists.

*** Variables ***@{ABC}abc@{XYZ}xyz@{NUM}123*** Test Cases ***FOR-IN-ZIP with multiple listsFOR    ${a}    ${x}    ${n}IN ZIP    ${ABC}    ${XYZ}    ${NUM}Log Many    ${a}    ${x}    ${n}ENDFOR-IN-ZIP with one variableFOR    ${items}IN ZIP    ${ABC}    ${XYZ}    ${NUM}Length Should Be    ${items}3Log Many    ${items}[0]    ${items}[1]    ${items}[2]END

Starting from Robot Framework 6.1, it is possible to configure what to do iflengths of the iterated items differ. By default, the shortest item defines howmany iterations there are and values at the end of longer ones are ignored.This can be changed by using themode option that has three possible values:

  • STRICT: Items must have equal lengths. If not, execution fails. This isthe same as usingstrict=True with Python'szip function.
  • SHORTEST: Items in longer items are ignored. Infinite iterators are supportedin this mode as long as one of the items is exhausted. This is the defaultbehavior.
  • LONGEST: The longest item defines how many iterations there are. Missingvalues in shorter items are filled-in with value specified using thefilloption orNone if it is not used. This is the same as using Python'szip_longest function except that it hasfillvalue argument instead offill.

All these modes are illustrated by the following examples:

*** Variables ***@{CHARACTERS}abcdf@{NUMBERS}123*** Test Cases ***STRICT mode    [Documentation]This loop fails due to lists lengths being different.FOR    ${c}    ${n}IN ZIP    ${CHARACTERS}    ${NUMBERS}mode=STRICTLog    ${c}:${n}ENDSHORTEST mode    [Documentation]This loop executes three times.FOR    ${c}    ${n}IN ZIP    ${CHARACTERS}    ${NUMBERS}mode=SHORTESTLog    ${c}:${n}ENDLONGEST mode    [Documentation]This loop executes five times.    ...On last two rounds `${n}` has value `None`.FOR    ${c}    ${n}IN ZIP    ${CHARACTERS}    ${NUMBERS}mode=LONGESTLog    ${c}:${n}ENDLONGEST mode with custom fill value    [Documentation]This loop executes five times.    ...On last two rounds `${n}` has value `0`.FOR    ${c}    ${n}IN ZIP    ${CHARACTERS}    ${NUMBERS}mode=LONGESTfill=0Log    ${c}:${n}END

Note

The behavior if list lengths differ will change in the futureso that theSTRICT mode will be the default. If that is not desired,theSHORTEST mode needs to be used explicitly.

Dictionary iteration

NormalFOR loops andFOR-IN-ENUMERATE loops support iterating over keysand values in dictionaries. This syntax requires at least one of the loopvalues to be adictionary variable.It is possible to use multiple dictionary variables and to give additionalitems inkey=value syntax. Items are iterated in the order they are definedand if same key gets multiple values the last value will be used.

*** Variables ***&{DICT}a=1b=2c=3*** Test Cases ***Dictionary iteration with FOR loopFOR    ${key}    ${value}IN    &{DICT}LogKey is '${key}' and value is '${value}'.ENDDictionary iteration with FOR-IN-ENUMERATE loopFOR    ${index}    ${key}    ${value}IN ENUMERATE    &{DICT}LogOn round${index} key is '${key}' and value is '${value}'.ENDMultiple dictionaries and extra items in 'key=value' syntax    &{more} =Create Dictionarye=5f=6FOR    ${key}    ${value}IN    &{DICT}d=4    &{more}g=7LogKey is '${key}' and value is '${value}'.END

Typically it is easiest to use the dictionary iteration syntax so that keysand values get separate variables like in the above examples. With normalFORloops it is also possible to use just a single variable that will becomea tuple containing the key and the value. If only one variable is used withFOR-IN-ENUMERATE loops, it becomes a tuple containing the index, the key andthe value. Two variables withFOR-IN-ENUMERATE loops means assigning the indexto the first variable and making the second variable a tuple containing the keyand the value.

*** Test Cases ***One loop variableFOR    ${item}IN    &{DICT}LogKey is '${item}[0]' and value is '${item}[1]'.ENDOne loop variable with FOR-IN-ENUMERATEFOR    ${item}IN ENUMERATE    &{DICT}LogOn round${item}[0] key is '${item}[1]' and value is '${item}[2]'.ENDTwo loop variables with FOR-IN-ENUMERATEFOR    ${index}    ${item}IN ENUMERATE    &{DICT}LogOn round${index} key is '${item}[0]' and value is '${item}[1]'.END

In addition to iterating over names and values in dictionaries, it is possibleto iterate over keys and then possibly fetch the value based on it. This syntaxrequires using dictionaries aslist variables:

*** Test Cases ***Iterate over keysFOR    ${key}IN    @{DICT}LogKey is '${key}' and value is '${DICT}[${key}]'.END

Note

Iterating over keys and values in dictionaries is a new feature inRobot Framework 3.2. With earlier version it is possible to iterateover dictionary keys like the last example above demonstrates.

Loop variable conversion

Variable type conversion works also with FOR loop variables. The desired typecan be added to any loop variable by using the familiar${name: type} syntax.

*** Test Cases ***Variable conversionFOR    ${value: bytes}INHello!Hyvä!\x00\x00\x07Log    ${value}formatter=reprENDFOR    ${index}    ${date: date}IN ENUMERATE2023-06-152025-05-30todayLog    ${date}formatter=reprENDFOR    ${item: tuple[str, date]}IN ENUMERATE2023-06-152025-05-30todayLog    ${item}formatter=reprEND

Note

Variable type conversion is new in Robot Framework 7.3.

Removing unnecessary keywords from outputs

FOR loops with multiple iterations often create lots of output andconsiderably increase the size of the generatedoutput andlog files.It is possible toremove or flatten unnecessary keywords using--removekeywords and--flattenkeywords command line options.

Repeating single keyword

FOR loops can be excessive in situations where there is only a need torepeat a single keyword. In these cases it is often easier to useBuiltIn keywordRepeat Keyword. This keyword takes akeyword and how many times to repeat it as arguments. The times torepeat the keyword can have an optional postfixtimes orxto make the syntax easier to read.

*** Test Cases ***ExampleRepeat Keyword5Some Keywordarg1arg2Repeat Keyword42 timesMy KeywordRepeat Keyword    ${var}Another Keywordargument

2.9.2   WHILE loops

WHILE loops combine features ofFOR loops andIF/ELSE structures.They specify a condition and repeat the loop body as long as the conditionremains true. This can be utilised, for example, to repeat a nondeterministic sequenceuntil the desired outcome happens, or in some cases they can be used as analternative toFOR loops.

Note

WHILE loops are new in Robot Framework 5.0.

BasicWHILE syntax

*** Test Cases ***ExampleVAR    ${rc}1WHILE    ${rc} != 0        ${rc} =Keyword that returns zero on successEND

TheWHILE loop condition is evaluated in Python so that Python builtins likelen() are available and modules are imported automatically to support usageslikemath.pi * math.pow(${radius}, 2) < 10.Normal variables like${rc} in the above example are replaced before evaluation, butvariables are also available in the evaluation namespace using the special$rc syntax.The latter approach is handy when the string representation of the variable cannot beused in the condition directly. For example, strings require quoting and multilinestrings and string themselves containing quotes cause additional problems. See theEvaluating expressions appendix for more information and examples related tothe evaluation syntax.

Starting from Robot Framework 6.1, the condition in aWHILE statement can be omitted.This is interpreted as the condition always being true, which may be useful with thelimit option described below.

LimitingWHILE loop iterations

WithWHILE loops, there is always a possibility to achieve an infinite loop,either by intention or by mistake. This happens when the loop condition neverbecomes false. While infinite loops have some utility in application programming,in automation an infinite loop is rarely a desired outcome. If such a loop occurswith Robot Framework, the execution must be forcefully stopped and no log or reportcan be created. For this reason,WHILE loops in Robot Framework have a defaultlimit of 10 000 iterations. If the limit is exceeded, the loop fails.

The limit can be set with thelimit configuration parameter either as a maximumiteration count or as a maximum time for the whole loop. When the limit is aniteration count, it is possible to use just integers like100 and to addtimesorx suffix after the value like100 times. When the limit is a timeout,it is possible to usetime strings like10 s or1 hour 10 minutes.The limit can also be disabled altogether by usingNONE (case-insensitive).All these options are illustrated by the examples below.

*** Test Cases ***Limit as iteration countWHILETruelimit=100LogThis is run 100 times.ENDWHILETruelimit=10 timesLogThis is run 10 times.ENDWHILETruelimit=42xLogThis is run 42 times.ENDLimit as timeWHILETruelimit=10 secondsLogThis is run 10 seconds.ENDNo limitWHILETruelimit=NONELogThis runs forever.END

Note

Support for usingtimes andx suffixes with iteration countsis new in Robot Framework 7.0.

Keywords in a loop are not forcefully stopped if the limit is exceeded. Insteadthe loop is exited similarly as if the loop condition would have become false.A major difference is that the loop status will beFAIL in this case.

Starting from Robot Framework 6.1, it is possible to useon_limit parameter toconfigure the behaviour when the limit is exceeded. It supports two valuespassandfail, case insensitively. If the value ispass, the execution will continuenormally when the limit is reached and the status of theWHILE loop will bePASS.The valuefail works similarly as the default behaviour, e.g. the loop and thetest will fail if the limit is exceeded.

*** Test Cases ***Continue when iteration limit is reachedWHILETruelimit=5on_limit=passLogLoop will be executed five timesENDLogThis will be executed normally.Continue when time limit is reachedWHILETruelimit=10son_limit=passLogLoop will be executed for 10 seconds.Sleep0.5sENDLogThis will be executed normally.

By default, the error message raised when the limit is reached isWHILE loop was aborted because it did not finish within the limit of 0.5seconds. Use the 'limit' argument to increase or remove the limit ifneeded.. Starting from Robot Framework 6.1, the error message can be changedwith theon_limit_message configuration parameter.

*** Test Cases ***Limit as iteration countWHILETruelimit=0.5son_limit_message=Custom While loop error messageLogThis is run 0.5 seconds.END

Note

on_limit_message configuration parameter is new in Robot Framework 6.1.

NestingWHILE loops

WHILE loops can be nested and also combined with other control structures:

*** Test Cases ***Nesting WHILEVAR    ${x}10WHILE    ${x} > 0VAR    ${y}    ${x}WHILE    ${y} > 0            ${y} =Evaluate    ${y} - 1ENDIF    ${x} > 5            ${x} =Evaluate    ${x} - 1ELSE            ${x} =Evaluate    ${x} - 2ENDEND

Removing unnecessary keywords from outputs

WHILE loops with multiple iterations often create lots of output andconsiderably increase the size of the generatedoutput andlog files.It is possible toremove or flatten unnecessary keywords using--removekeywords and--flattenkeywords command line options.

2.9.3   Loop control usingBREAK andCONTINUE

BothFOR andWHILE loop execution can be controlled withBREAK andCONTINUEstatements. The former exits the whole loop prematurely and the latter stopsexecuting the current loop iteration and continues to the next one. In practicethey have the same semantics asbreak andcontinue statements in Python, Java,and many other programming languages.

BothBREAK andCONTINUE are typically used conditionally withIF/ELSEorTRY/EXCEPT structures, and especially theinline IF syntax is oftenconvenient with them. These statements must be used in the loop body,possibly inside the aforementioned control structures, and using them inkeyword called in the loop body is invalid.

*** Test Cases ***BREAK with FOR    ${text} =Set VariablezeroFOR    ${var}INonetwothreeIF'${var}' == 'two'BREAK        ${text} =Set Variable    ${text}-${var}ENDShould Be Equal    ${text}zero-oneCONTINUE with FOR    ${text} =Set VariablezeroFOR    ${var}INonetwothreeIF'${var}' == 'two'CONTINUE        ${text} =Set Variable    ${text}-${var}ENDShould Be Equal    ${text}zero-one-threeCONTINUE and BREAK with WHILEWHILETrueTRY             ${value} =Do SomethingEXCEPTCONTINUEENDDo something with value    ${value}BREAKENDInvalid BREAK usage    [Documentation]BREAK and CONTINUE can only be used in the loop body,    ...not in keywords used in the loop.FOR    ${var}INonetwothreeInvalid BREAKEND*** Keywords ***Invalid BREAK    [Documentation]This keyword fails due to invalid syntax.BREAK

Note

BREAK andCONTINUE statements are new in Robot Framework 5.0 similarlyasWHILE. Earlier versions supported controllingFOR loops usingBuiltIn keywordsExit For Loop,Exit For Loop If,Continue For Loop andContinue For Loop If. Thesekeywords still continue to work, but they will be deprecated and removedin the future.

Note

Also theRETURN statement can be used to a exit loop. It only workswhen loops are used inside auser keyword.

2.9.4   IF/ELSE syntax

Sometimes there is a need to execute some keywords conditionally. Startingfrom Robot Framework 4.0 there is a separateIF/ELSE syntax, butthere are alsoother ways to execute keywords conditionally. Notice that ifthe logic gets complicated, it is typically better to move it into atest library.

BasicIF syntax

Robot Framework's nativeIF syntax starts withIF (case-sensitive) andends withEND (case-sensitive). TheIF marker requires exactly one value that isthe condition to evaluate. Keywords to execute if the condition is true are on theirown rows between theIF andEND markers. Indenting keywords in theIF block ishighly recommended but not mandatory.

In the following example keywordsSome keyword andAnother keywordare executed if${rc} is greater than zero:

*** Test Cases ***ExampleIF    ${rc} > 0Some keywordAnother keywordEND

The condition is evaluated in Python so that Python builtins likelen() are available and modules are imported automatically to support usages likeplatform.system() == 'Linux' andmath.ceil(${x}) == 1.Normal variables like${rc} in the above example are replaced before evaluation, butvariables are also available in the evaluation namespace using the special$rc syntax.The latter approach is handy when the string representation of the variable cannot beused in the condition directly. For example, strings require quoting and multilinestrings and string themselves containing quotes cause additional problems. For moreinformation and examples related the evaluation syntax see theEvaluating expressionsappendix.

ELSE branches

Like most other languages supporting conditional execution, Robot FrameworkIFsyntax also supportsELSE branches that are executed if theIF condition isnot true.

In this exampleSome keyword is executed if${rc} is greater thanzero andAnother keyword is executed otherwise:

*** Test Cases ***ExampleIF    ${rc} > 0Some keywordELSEAnother keywordEND

ELSE IF branches

Robot Framework also supportsELSE IF branches that have their own conditionthat is evaluated if the initial condition is not true. There can be any numberofELSE IF branches and they are gone through in the order they are specified.If one of theELSE IF conditions is true, the block following it is executedand remainingELSE IF branches are ignored. An optionalELSE branch can followELSE IF branches and it is executed if all conditions are false.

In the following example different keyword is executed depending on is${rc} positive,negative, zero, or something else like a string orNone:

*** Test Cases ***ExampleIF$rc > 0Positive keywordELSE IF$rc < 0Negative keywordELSE IF$rc == 0Zero keywordELSEFailUnexpected rc:${rc}END

Notice that this example uses the${rc} variable in the special$rc format toavoid evaluation failures if it is not a number. See the aforementionedEvaluating expressions appendix for more information about this syntax.

InlineIF

NormalIF/ELSE structure is a bit verbose if there is a need to execute onlya single statement. An alternative to it is using inlineIF syntax wherethe statement to execute follows theIF marker and condition directly andnoEND marker is needed. For example, the following two keywords areequivalent:

*** Keywords ***Normal IFIF$condition1KeywordargumentENDIF$condition2RETURNENDInline IFIF$condition1KeywordargumentIF$condition2RETURN

The inlineIF syntax supports alsoELSE andELSE IF branches:

*** Keywords ***Inline IF/ELSEIF$conditionKeywordargumentELSEAnother KeywordInline IF/ELSE IF/ELSEIF$cond1Keyword 1ELSE IF$cond2Keyword 2ELSE IF$cond3Keyword 3ELSEKeyword 4

As the latter example above demonstrates, inlineIF with severalELSE IFandELSE branches starts to get hard to understand. Long inlineIFstructures can besplit into multiple lines using the common...continuation syntax, but using a normalIF/ELSE structure or moving the logicinto atest library is probably a better idea. Each inlineIF branch cancontain only one statement. If more statements are needed, normalIF/ELSEstructure needs to be used instead.

If there is a need for an assignment with inlineIF, the variable or variablesto assign must be before the startingIF. Otherwise the logic is exactlythe same as whenassigning variables based on keyword return values. Ifassignment is used and no branch is run, the variable gets valueNone.

*** Keywords ***Inline IF/ELSE with assignment    ${var} =IF$conditionKeywordargumentELSEAnother KeywordInline IF/ELSE with assignment having multiple variables    ${host}    ${port} =IF$productionGet Production ConfigELSEGet Testing Config

Note

InlineIF syntax is new in Robot Framework 5.0.

NestedIF structures

IF structures can be nested with each others and withFOR loops.This is illustrated by the following example using advanced features suchasFOR-IN-ENUMERATE loop,named-only arguments with user keywords andinline Python evaluation syntax (${{len(${items})}}):

*** Keywords ***Log items    [Arguments]    @{items}    ${log_values}=TrueIFnot${items}Log to consoleNo items.ELSE IFlen(${items}) == 1IF    ${log_values}Log to consoleOne item:${items}[0]ELSELog to consoleOne item.ENDELSELog to console    ${{len(${items})}} items.IF    ${log_values}FOR    ${index}    ${item}IN ENUMERATE    @{items}start=1Log to consoleItem${index}:${item}ENDENDEND*** Test Cases ***No itemsLog itemsOne item without logging valueLog itemsxxxlog_values=FalseMultiple itemsLog itemsabc

Other ways to execute keywords conditionally

There are also other methods to execute keywords conditionally:

  • The name of the keyword used as a setup or a teardown withsuites,tests andkeywords can be specified using a variable. This facilitates changing them,for example, from the command line.
  • TheBuiltIn keywordRun Keyword takes a keyword to actuallyexecute as an argument and it can thus be a variable. The value ofthe variable can, for example, be got dynamically from an earlierkeyword or given from the command line.
  • TheBuiltIn keywordsRun Keyword If andRun Keyword Unlessexecute a named keyword only if a certain expression is true or false, respectively.The newIF/ELSE syntax explained above is generally recommended, though.
  • AnotherBuiltIn keyword,Set Variable If, can be used to setvariables dynamically based on a given expression.
  • There are severalBuiltIn keywords that allow executing a namedkeyword only if a test case or test suite has failed or passed.

2.9.5   TRY/EXCEPT syntax

When a keyword fails, Robot Framework's default behavior is to stop the currenttest and executes its possibleteardown. There can, however, be needs to handlethese failures during execution as well. Robot Framework 5.0 introduces nativeTRY/EXCEPT syntax for this purpose, but there alsoother ways to handle errors.

Robot Framework'sTRY/EXCEPT syntax is inspired by Python'sexception handlingsyntax. It has sameTRY,EXCEPT,ELSE andFINALLY branches as Python andthey also mostly work the same way. A difference is that Python uses lower casetry,except, etc. but with Robot Framework all this kind of syntax must useupper case letters. A bigger difference is that with Python exceptions are objectsand with Robot Framework you are dealing with error messages as strings.

Note

It is not possible to catch errors caused by invalid syntax or errorsthatstop the whole execution.

Catching exceptions withEXCEPT

The basicTRY/EXCEPT syntax can be used to handle failures based onerror messages:

*** Test Cases ***First exampleTRYSome KeywordEXCEPTError messageError Handler KeywordENDKeyword Outside

In the above example, ifSome Keyword passes, theEXCEPT branch is not runand execution continues after theTRY/EXCEPT structure. If the keyword failswith a messageError message (case-sensitive), theEXCEPT branch is executed.If theEXCEPT branch succeeds, execution continues after theTRY/EXCEPTstructure. If it fails, the test fails and remaining keywords are not executed.IfSome Keyword fails with any other exception, that failure is not handledand the test fails without executing remaining keywords.

There can be more than oneEXCEPT branch. In that case they are matched oneby one and the first matching branch is executed. OneEXCEPT can also havemultiple messages to match, and such a branch is executed if any of its messagesmatch. In all these cases messages can be specified using variables in additionto literal strings.

*** Test Cases ***Multiple EXCEPT branchesTRYSome KeywordEXCEPTError message# Try matching this first.Error Handler 1EXCEPTAnother error# Try this if above did not match.Error Handler 2EXCEPT    ${message}# Last match attempt, this time using a variable.Error Handler 3ENDMultiple messages with one EXCEPTTRYSome KeywordEXCEPTError messageAnother error    ${message}# Match any of these.Error handlerEND

It is also possible to have anEXCEPT without messages, in which case it matchesany error. There can be only one suchEXCEPT and it must follow possibleotherEXCEPT branches:

*** Test Cases ***Match any errorTRYSome KeywordEXCEPT# Match any error.Error HandlerENDMatch any after testing more specific errorsTRYSome KeywordEXCEPTError message# Try matching this firstError Handler 1EXCEPT# Match any that did not match the above.Error Handler 2END

Matching errors using patterns

By default matching an error usingEXCEPT requires an exact match. That can bechanged using a configuration optiontype= as an argument to the except clause.Valid values for the option areGLOB,REGEXP orSTART (case-insensitive)to make the match aglob pattern match, aregular expression match, orto match only the beginning of the error, respectively. Using valueLITERAL has the same effect as the default behavior. If anEXCEPT has multiplemessages, this option applies to all of them. The value of the optioncan be defined with a variable as well.

*** Variables ***${MATCH TYPE}regexp*** Test Cases ***Glob patternTRYSome KeywordEXCEPTValueError: *type=GLOBError Handler 1EXCEPT[Ee]rror ?? occurred    ${pattern}type=globError Handler 2ENDRegular expressionTRYSome KeywordEXCEPTValueError: .*type=${MATCH TYPE}Error Handler 1EXCEPT[Ee]rror \\d+ occurredtype=Regexp# Backslash needs to be escaped.Error Handler 2ENDMatch startTRYSome KeywordEXCEPTValueError:    ${beginning}type=startError HandlerENDExplicit exact matchTRYSome KeywordEXCEPTValueError: invalid literal for int() with base 10: 'ooops'type=LITERALError HandlerEXCEPTError 13 occurredtype=LITERALError Handler 2END

Note

Remember that the backslash character often used with regular expressionsis anescape character in Robot Framework data. It thus needs to beescaped with another backslash when using it in regular expressions.

Capturing error message

Whenmatching errors using patterns and when usingEXCEPT without anymessages to match any error, it is often useful to know the actual error thatoccurred. Robot Framework supports that by making it possible to capturethe error message into a variable by addingAS  ${var} at theend of theEXCEPT statement:

*** Test Cases ***Capture errorTRYSome KeywordEXCEPTValueError: *type=GLOBAS   ${error}Error Handler 1    ${error}EXCEPT[Ee]rror \\d+(Invalid|Bad) usagetype=REGEXPAS    ${error}Error Handler 2    ${error}EXCEPTAS    ${error}Error Handler 3    ${error}END

UsingELSE to execute keywords when there are no errors

OptionalELSE branches make it possible to execute keywords if there is no error.There can be only oneELSE branch and it is allowed only after one or moreEXCEPT branches:

*** Test Cases ***ELSE branchTRYSome KeywordEXCEPTXLogError 'X' occurred!EXCEPTYLogError 'Y' occurred!ELSELogNo error occurred!ENDKeyword Outside

In the above example, ifSome Keyword passes, theELSE branch is executed,and if it fails with messageX orY, the appropriateEXCEPT branch run.In all these cases execution continues after the wholeTRY/EXCEPT/ELSE structure.IfSome Keyword fail any other way,EXCEPT andELSE branches are not runand theTRY/EXCEPT/ELSE structure fails.

To handle both the case when there is any error and when there is no error,it is possible to use anEXCEPT without any message in combination with anELSE:

*** Test Cases ***Handle everythingTRYSome KeywordEXCEPTAS    ${err}LogError occurred:${err}ELSELogNo error occurred!END

UsingFINALLY to execute keywords regardless are there errors or not

OptionalFINALLY branches make it possible to execute keywords both when thereis an error and when there is not. They are thus suitable for cleaning upafter a keyword execution somewhat similarly asteardowns. There can be only oneFINALLY branch and it must always be last. They can be used in combination withEXCEPT andELSE branches and having alsoTRY/FINALLY structure is possible:

*** Test Cases ***TRY/EXCEPT/ELSE/FINALLYTRYSome keywordEXCEPTLogError occurred!ELSELogNo error occurred.FINALLYLogAlways executed.ENDTRY/FINALLYOpen ConnectionTRYUse ConnectionFINALLYClose ConnectionEND

Other ways to handle errors

There are also other methods to execute keywords conditionally:

  • TheBuiltIn keywordRun Keyword And Expect Error executes a namedkeyword and expects that it fails with a specified error message. It is basicallythe same as usingTRY/EXCEPT with a specified message. The syntax to specifythe error message is also identical except that this keyword uses glob patternmatching, not exact match, by default. Using the nativeTRY/EXCEPT functionalityis generally recommended unless there is a need to support older Robot Frameworkversions that do not support it.
  • TheBuiltIn keywordRun Keyword And Ignore Error executes a named keywordand returns its status as stringPASS orFAIL along with possible return valueor error message. It is basically the same as usingTRY/EXCEPT/ELSE so thatEXCEPT catches all errors. Using the native syntax is recommended unlessold Robot Framework versions need to be supported.
  • TheBuiltIn keywordRun Keyword And Return Status executes a named keywordand returns its status as a Boolean true or false. It is a wrapper for theaforementionedRun Keyword And Ignore Error. The native syntax isnowadays recommended instead.
  • Test teardowns andkeyword teardowns can be used for cleaning up activitiessimilarly asFINALLY branches.
  • When keywords are implemented in Python basedlibraries, all Python's errorhandling features are readily available. This is the recommended approachespecially if needed logic gets more complicated.

2.9.6   GROUP syntax

TheGROUP syntax allows grouping related keywords and control structures together:

*** Test Cases ***Valid loginGROUPOpen browser to login pageOpen Browser    ${LOGIN URL}Title Should BeLogin PageENDGROUPSubmit credentialsInput Usernameusername_fielddemoInput Passwordpassword_fieldmodeClick Buttonlogin_buttonENDGROUPLogin should have succeededTitle Should BeWelcome PageENDAnonymous groupGROUPLogGroup name is optional.ENDNestingGROUPGROUPNested groupLogGroups can be nested.ENDIFTrueGROUPLogGroups can also be nested with other control structures.ENDENDEND

As the above examples demonstrates, groups can have a name, but the name isoptional. Groups can also be nested freely with each others and with othercontrol structures.

User keywords are in general recommended over theGROUP syntax, becausethey are reusable and because they simplify tests or keywords where they areused by hiding and encapsulating lower level details. In the log file userkeywords and groups look the same, though, except that instead of aKEYWORDlabel there is aGROUP label.

All groups within a test or a keyword share the same variable namespace.This means that, unlike when using keywords, there is no need to use argumentsor return values for sharing values. This can be a benefit in simple cases,but if there are lot of variables, the benefit can turn into a problem andcause a huge mess.

Note

TheGROUP syntax is new in Robot Framework 7.2.

GROUP with templates

TheGROUP syntax can be used for grouping iterations withtest templates:

*** Settings ***LibraryStringTest TemplateUpper case should be*** Test Cases ***Template exampleGROUPASCII charactersaAzZENDGROUPLatin-1 charactersäÄßSSENDGROUPNumbers1199END*** Keywords ***Upper case should be    [Arguments]    ${char}    ${expected}    ${actual} =Convert To Upper Case    ${char}Should Be Equal    ${actual}    ${expected}

Programmatic usage

One of the primary usages for groups is making it possible to create structuredtests and user keywords programmatically. For example, the followingpre-run modifier adds a group with two keywords at the end of each modifiedtest. Groups can be added also bylisteners that use thelistener API version 3.

fromrobot.apiimportSuiteVisitorclassGroupAdder(SuiteVisitor):defstart_test(self,test):group=test.body.create_group(name='Example')group.body.create_keyword(name='Log',args=['Hello, world!'])group.body.create_keyword(name='No Operation')

2.10   Advanced features

2.10.1   Handling keywords with same names

Keywords that are used with Robot Framework are eitherlibrarykeywords oruser keywords. The former come fromstandardlibraries orexternal libraries, and the latter are eithercreated in the same file where they are used or then imported fromresource files. When many keywords are in use, it is quite commonthat some of them have the same name, and this section describes how tohandle possible conflicts in these situations.

Keyword scopes

When only a keyword name is used and there are several keywords withthat name, Robot Framework attempts to determine which keyword has thehighest priority based on its scope. The keyword's scope is determinedon the basis of how the keyword in question is created:

  1. Created as a user keyword in the currently executedsuite file.These keywords have the highest priority and they are always used, evenif there are other keywords with the same name elsewhere.
  2. Created in a resource file and imported either directly orindirectly from another resource file. This is the second-highestpriority.
  3. Created in an external test library. These keywords are used, ifthere are no user keywords with the same name. However, if there isa keyword with the same name in the standard library, a warning isdisplayed.
  4. Created in a standard library. These keywords have the lowestpriority.

Specifying a keyword explicitly

Scopes alone are not a sufficient solution, because there can bekeywords with the same name in several libraries or resources, andthus, they provide a mechanism to use only the keyword of thehighest priority. In such cases, it is possible to usethe full nameof the keyword, where the keyword name is prefixed with the name ofthe resource or library and a dot is a delimiter.

With library keywords, the long format means only using the formatLibraryName.Keyword Name. For example, the keywordRunfrom theOperatingSystem library could be used asOperatingSystem.Run, even if there was anotherRunkeyword somewhere else. If the library is in a module or package, thefull module or package name must be used (for example,com.company.Library.Some Keyword). If acustom name is givento a library when importing it, the specified name must beused also in the full keyword name.

Resource files are specified in the full keyword name, similarly aslibrary names. The name of the resource is derived from the basenameof the resource file without the file extension. For example, thekeywordExample in a resource filemyresources.html canbe used asmyresources.Example. Note that this syntax does notwork, if several resource files have the same basename. In suchcases, either the files or the keywords must be renamed. The full nameof the keyword is case-, space- and underscore-insensitive, similarlyas normal keyword names.

Specifying explicit priority between libraries and resources

If there are multiple conflicts between keywords, specifying all the keywordsin the long format can be quite a lot work. Using the long format also makes itimpossible to create dynamic test cases or user keywords that work differentlydepending on which libraries or resources are available. A solution to both ofthese problems is specifying the keyword priorities explicitly using the keywordSet Library Search Order from theBuiltIn library.

Note

Although the keyword has the wordlibrary in its name, it worksalso with resource files. As discussed above, keywords in resourcesalways have higher priority than keywords in libraries, though.

TheSet Library Search Order accepts an ordered list or libraries andresources as arguments. When a keyword name in the test data matches multiplekeywords, the first library or resource containing the keyword is selected andthat keyword implementation used. If the keyword is not found from any of thespecified libraries or resources, execution fails for conflict the same way aswhen the search order is not set.

For more information and examples, see the documentation of the keyword.

2.10.2   Timeouts

Sometimes keywords may take exceptionally long time to execute or just hangendlessly. Robot Framework allows you to set timeouts both fortest casesanduser keywords, and if a test or keyword is not finished within thespecified time, the keyword that is currently being executed is forcefullystopped.

Stopping keywords in this manner may leave the library, the test environmentor the system under test to an unstable state, and timeouts are recommendedonly when there is no safer option available. In general, libraries should beimplemented so that keywords cannot hang or that they have their own timeoutmechanism.

Test case timeout

The test case timeout can be set either by using theTest Timeoutsetting in the Setting section or the[Timeout] setting withindividual test cases.Test Timeout defines a default timeoutfor all the test cases in that suite, whereas[Timeout] appliesa timeout to a particular test case and overrides the possible default value.

Using an empty[Timeout] means that the test has no timeout evenwhenTest Timeout is used. It is also possible to use explicitNONE value for this purpose. The timeout is effectively ignored also ifits value is zero or negative.

Regardless of where the test timeout is defined, the value given to itcontains the duration of the timeout. The duration must be given in RobotFramework'stime format, that is, either directly in seconds like10or in a format like1 minute 30 seconds. Timeouts can also be specifiedasvariables making it possible to give them, for example, from the commandline.

If there is a timeout and it expires, the keyword that is currently runningis stopped and the test case fails. Keywords executed as part oftestteardown are not interrupted if a test timeout occurs, though, but the testis nevertheless marked failed. If a keyword in teardown may hang, it can bestopped by usinguser keyword timeouts.

*** Settings ***Test Timeout2 minutes*** Test Cases ***Default timeout    [Documentation]Default timeout from Settings is used.Some KeywordargumentOverride    [Documentation]Override default, use 10 seconds timeout.    [Timeout]10Some KeywordargumentVariables    [Documentation]It is possible to use variables too.    [Timeout]    ${TIMEOUT}Some KeywordargumentNo timeout    [Documentation]Empty timeout means no timeout even when Test Timeout has been used.    [Timeout]Some KeywordargumentNo timeout 2    [Documentation]Disabling timeout with NONE works too and is more explicit.    [Timeout]NONESome Keywordargument

User keyword timeout

Timeouts can be set for user keywords using the[Timeout] setting.The syntax is exactly the same as withtest case timeout, but user keywordtimeouts do not have any default value. If a user keyword timeout is specifiedusing a variable, the value can be given also as a keyword argument.

*** Keywords ***Hardcoded    [Arguments]    ${arg}    [Timeout]1 minute 42 secondsSome Keyword    ${arg}Configurable    [Arguments]    ${arg}    ${timeout}    [Timeout]    ${timeout}Some Keyword    ${arg}Run Keyword with Timeout    [Arguments]    ${keyword}    @{args}    &{kwargs}    ${timeout}=1 minute    [Documentation]Wrapper that runs another keyword with a configurable timeout.    [Timeout]    ${timeout}Run Keyword    ${keyword}    @{args}    &{kwargs}

A user keyword timeout is applicable during the execution of that userkeyword. If the total time of the whole keyword is longer than thetimeout value, the currently executed keyword is stopped. User keywordtimeouts are applicable also during a test case teardown, whereas testtimeouts are not.

If both the test case and some of its keywords (or several nestedkeywords) have a timeout, the active timeout is the one with the leasttime left.

Note

With earlier Robot Framework versions it was possible to specifya custom error message to use if a timeout expires. Thisfunctionality was deprecated in Robot Framework 3.0.1 and removedin Robot Framework 3.2.

2.10.3   Parallel execution of keywords

When parallel execution is needed, it must be implemented in test librarylevel so that the library executes the code on background. Typically thismeans that the library needs a keyword likeStart Something thatstarts the execution and returns immediately, and another keyword likeGet Results From Something that waits until the result is availableand returns it. SeeProcess library keywordsStart ProcessandWait For Process for an example.

3   Executing test cases

3.1   Basic usage

Robot Framework test cases are executed from the command line, and theend result is, by default, anoutput file in XML format and an HTMLreport andlog. After the execution, output files can be combined andotherwisepost-processed with the Rebot tool.

3.1.1   Starting test execution

Synopsis

robot [options] datapython -m robot [options] datapython path/to/robot/ [options] data

Execution is normally started using therobot command created as part ofinstallation. Alternatively it is possible to execute the installedrobotmodule using the selected Python interpreter. This is especially convenientif Robot Framework has been installed under multiple Python versions.Finally, if you know where the installedrobot directory exists, it canbe executed using Python as well.

Regardless of execution approach, the path (or paths) to the test data to beexecuted is given as an argument after the command. Additionally, differentcommand line options can be used to alter the test execution or generatedoutputs in many ways.

Specifying test data to be executed

Robot Framework test cases are created infiles anddirectories,and they are executed by giving the path to the file or directory inquestion to the selected runner script. The path can be absolute or,more commonly, relative to the directory where tests are executedfrom. The given file or directory creates the top-level test suite,which, by default, gets its name from thefile or directory name.Different execution possibilitiesare illustrated in the examples below. Note that in these examples, aswell as in other examples in this section, only therobot scriptis used, but other execution approaches could be used similarly.

robot tests.robotrobot path/to/my_tests/robot c:\robot\tests.robot

Note

When executing adirectory, all files and directories starting witha dot (.) or an underscore (_) are ignored and,by default, only files with the.robot extension executed.See theSelecting files to parse section for more details.

It is also possible to give paths to several test case files ordirectories at once, separated with spaces. In this case, RobotFramework creates the top-level test suite automatically, andthe specified files and directories become its child test suites. The nameof the created test suite is got from child suite names byconcatenating them together with an ampersand (&) and spaces. For example,the name of the top-level suite in the first example below isMy Tests & Your Tests. These automatically created names areoften quite long and complicated. In most cases, it is thus better touse the--name option for overriding it, as in the secondexample below:

robot my_tests.robot your_tests.robotrobot --name Example path/to/tests/pattern_*.robot

Starting from Robot Framework 6.1, it is also possible to define atest suite initialisation file for the automatically created top-levelsuite. The path to the init file is given similarly to thetest case files:

robot __init__.robot my_tests.robot other_tests.robot

3.1.2   Using command line options

Robot Framework provides a number of command line options that can beused to control how test cases are executed and what outputs aregenerated. This section explains the option syntax, and whatoptions actually exist. How they can be used is discussed elsewherein this chapter.

Using options

When options are used, they must always be given between the runnerscript and the data sources. For example:

robot -L debug my_tests.robotrobot --include smoke --variable HOST:10.0.0.42 path/to/tests/

Short and long options

Options always have a long name, such as--name, and themost frequently needed options also have a short name, such as-N. In addition to that, long options can be shortened aslong as they are unique. For example,--logle DEBUG works,while--lo log.html does not, because the former matches only--loglevel, but the latter matches several options. Shortand shortened options are practical when executing test casesmanually, but long options are recommended instart-up scripts,because they are easier to understand.

The long option names are case-insensitive and hyphen-insensitive,which facilitates writing option names in an easy-to-read format.For example,--SuiteStatLevel and--suite-stat-levelare equivalent to, but easier to read than,--suitestatlevel.

Note

Long options being hyphen-insensitive is new in Robot Framework 6.1.

Setting option values

Most of the options require a value, which is given after the optionname. Both short and long options accept the value separatedfrom the option name with a space, as in--include tagor-i tag. With long options, the separator can also be theequals sign, for example--include=tag, and with short options theseparator can be omitted, as in-itag.

Some options can be specified several times. For example,--variable VAR1:value --variable VAR2:another sets twovariables. If the options that take only one value are used severaltimes, the value given last is effective.

Disabling options accepting no values

Options accepting no values can be disabled by using the same option againwithno prefix added or dropped. The last option has precedence regardlessof how many times options are used. For example,--dryrun --dryrun --nodryrun--nostatusrc --statusrc would not activate the dry-run mode and would returnnormal status rc.

Simple patterns

Many command line options take arguments assimple patterns. Theseglob-like patterns are matched according to the following rules:

  • * matches any string, even an empty string.
  • ? matches any single character.
  • [abc] matches one character in the bracket.
  • [!abc] matches one character not in the bracket.
  • [a-z] matches one character from the range in the bracket.
  • [!a-z] matches one character not from the range in the bracket.
  • Unlike with glob patterns normally, path separator characters/ and\ and the newline character\n are matches by the abovewildcards.
  • Unless noted otherwise, pattern matching is case, space, and underscore insensitive.

Examples:

--test Example*        # Matches tests with name starting 'Example'.--test Example[1-2]    # Matches tests 'Example1' and 'Example2'.--include f??          # Matches tests with a tag that starts with 'f' is three characters long.

All matching in above examples is case, space and underscore insensitive.For example, the second example would also match test namedexample 1.

If the matched text happens to contain some of the wildcard characters andthey need to be matched literally, it is possible to do that by usingthe[...] syntax. The pattern[*] matches the literal* character,[?] matches?, and[[] matches[. Lone[ and] do not need tobe escaped.

Note

Support for brackets like[abc] and[!a-z] is new inRobot Framework 3.1.

Tag patterns

Most tag related options accept arguments astag patterns. They support samewildcards assimple patterns (e.g.examp??,ex*le), but they also supportAND,OR andNOT operators explained below. These operators can beused for combining two or more individual tags or patterns together.

AND or&

The whole pattern matches if all individual patterns match.AND and& are equivalent:

--include fooANDbar     # Matches tests containing tags 'foo' and 'bar'.--exclude xx&yy&zz      # Matches tests containing tags 'xx', 'yy', and 'zz'.
OR

The whole pattern matches if any individual pattern matches:

--include fooORbar      # Matches tests containing either tag 'foo' or tag 'bar'.--exclude xxORyyORzz    # Matches tests containing any of tags 'xx', 'yy', or 'zz'.
NOT

The whole pattern matches if the pattern on the left side matches butthe one on the right side does not. If used multiple times, none ofthe patterns after the firstNOT must not match:

--include fooNOTbar     # Matches tests containing tag 'foo' but not tag 'bar'.--exclude xxNOTyyNOTzz  # Matches tests containing tag 'xx' but not tag 'yy' or tag 'zz'.

The pattern can also start withNOTin which case the pattern matches if the pattern afterNOT does not match:

--include NOTfoo        # Matches tests not containing tag 'foo'--include NOTfooANDbar  # Matches tests not containing tags 'foo' and 'bar'

The above operators can also be used together. The operator precedence,from highest to lowest, isAND,OR andNOT:

--include xANDyORz      # Matches tests containing either tags 'x' and 'y', or tag 'z'.--include xORyNOTz      # Matches tests containing either tag 'x' or 'y', but not tag 'z'.--include xNOTyANDz     # Matches tests containing tag 'x', but not tags 'y' and 'z'.

Although tag matching itself is case-insensitive, all operators arecase-sensitive and must be written with upper case letters. If tags themselveshappen to contain upper caseAND,OR orNOT, they need to specifiedusing lower case letters to avoid accidental operator usage:

--include port          # Matches tests containing tag 'port', case-insensitively--include PORT          # Matches tests containing tag 'P' or 'T', case-insensitively--exclude handoverORportNOTnotification

ROBOT_OPTIONS andREBOT_OPTIONS environment variables

Environment variablesROBOT_OPTIONS andREBOT_OPTIONS can beused to specify default options fortest execution andresultpost-processing, respectively. The options and their values must bedefined as a space separated list and they are placed in front of anyexplicit options on the command line. The main use case for theseenvironment variables is setting global default values for certain options toavoid the need to repeat them every time tests are run or Rebot used.

exportROBOT_OPTIONS="--outputdir results --tagdoc 'mytag:Example doc with spaces'"robottests.robotexportREBOT_OPTIONS="--reportbackground blue:red:yellow"rebot--nameexampleoutput.xml

3.1.3   Test results

Command line output

The most visible output from test execution is the output displayed inthe command line. All executed test suites and test cases, as well astheir statuses, are shown there in real time. The example below shows theoutput from executing a simple test suite with only two test cases:

==============================================================================Example test suite==============================================================================First test :: Possible test documentation                             | PASS |------------------------------------------------------------------------------Second test                                                           | FAIL |Error message is displayed here==============================================================================Example test suite                                                    | FAIL |2 tests, 1 passed, 1 failed==============================================================================Output:  /path/to/output.xmlReport:  /path/to/report.htmlLog:     /path/to/log.html

There is also a notification on the consolewhenever a top-level keyword in a test case ends. A green dot is used ifa keyword passes and a red F if it fails. These markers are written to the endof line and they are overwritten by the test status when the test itself ends.Writing the markers is disabled if console output is redirected to a file.

Generated output files

The command line output is very limited, and separate output files arenormally needed for investigating the test results. As the exampleabove shows, three output files are generated by default. The firstone is in XML format and contains all the information about testexecution. The second is a higher-level report and the third is a moredetailed log file. These files and other possible output files arediscussed in more detail in the sectionDifferent output files.

Return codes

Runner scripts communicate the overall test execution status to thesystem running them using return codes. When the execution startssuccessfully and no tests fail, the return code is zero.All possible return codes are explained in the table below.

Possible return codes
RCExplanation
0All tests passed.
1-249Returned number of tests failed.
250250 or more failures.
251Help or version information printed.
252Invalid test data or command line options.
253Test execution stopped by user.
255Unexpected internal error.

Return codes should always be easily available after the execution,which makes it easy to automatically determine the overall executionstatus. For example, in bash shell the return code is in specialvariable$?, and in Windows it is in%ERRORLEVEL%variable. If you use some external tool for running tests, consult itsdocumentation for how to get the return code.

The return code can be set to 0 even if there are failures usingthe--NoStatusRC command line option. This might be useful, forexample, in continuous integration servers where post-processing of resultsis needed before the overall status of test execution can be determined.

Note

Same return codes are also used withRebot.

Errors and warnings during execution

During the test execution there can be unexpected problems likefailing to import a library or a resource file or a keyword beingdeprecated. Depending on the severity such problems are categorizedas errors or warnings and they are written into the console (using thestandard error stream), shown on a separateTest Execution Errorssection in log files, and also written into Robot Framework's ownsystem log. Normally these errors and warnings are generated by RobotFramework itself, but libraries can also logerrors and warnings.Example below illustrates how errors and warnings look like in the log file.

20090322 19:58:42.528ERRORError in file '/home/robot/tests.robot' in table 'Setting' in element on row 2: Resource file 'resource.robot' does not exist
20090322 19:58:43.931WARNKeyword 'SomeLibrary.Example Keyword' is deprecated. Use keyword `Other Keyword` instead.

3.1.4   Argument files

Argument files allow placing all or some command line options and argumentsinto an external file where they will be read. This avoids the problems withcharacters that are problematic on the command line. If lot of options orarguments are needed, argument files also prevent the command that is used onthe command line growing too long.

Argument files are taken into use with--argumentfile (-A) optionalong with possible other command line options.

Note

Unlike otherlong command line options,--argumentfilecannot be given in shortened format like--argumentf.

Argument file syntax

Argument files can contain both command line options and paths to the test data,one option or data source per line. Both short and long options are supported,but the latter are recommended because they are easier to understand.Argument files can contain any characters without escaping, but spaces inthe beginning and end of lines are ignored. Additionally, empty lines andlines starting with a hash mark (#) are ignored:

--doc This is an example (where "special characters" are ok!)--metadata X:Value with spaces--variable VAR:Hello, world!# This is a commentpath/to/my/tests

In the above example the separator between options and their values is a singlespace. It is possible to use either an equalsign (=) or any number of spaces. As an example, the following three lines areidentical:

--name An Example--name=An Example--name       An Example

If argument files contain non-ASCII characters, they must be saved usingUTF-8 encoding.

Using argument files

Argument files can be used either alone so that they contain all the optionsand paths to the test data, or along with other options and paths. Whenan argument file is used with other arguments, its contents are placed intothe original list of arguments to the same place where the argument fileoption was. This means that options in argument files can override optionsbefore it, and its options can be overridden by options after it. It is possibleto use--argumentfile option multiple times or even recursively:

robot --argumentfile all_arguments.robotrobot --name Example --argumentfile other_options_and_paths.robotrobot --argumentfile default_options.txt --name Example my_tests.robotrobot -A first.txt -A second.txt -A third.txt tests.robot

Reading argument files from standard input

Special argument file nameSTDIN can be used to read arguments from thestandard input stream instead of a file. This can be useful when generatingarguments with a script:

generate_arguments.sh | robot --argumentfile STDINgenerate_arguments.sh | robot --name Example --argumentfile STDIN tests.robot

3.1.5   Getting help and version information

Both when executing test cases and when post-processing outputs, it is possibleto get command line help with the option--help (-h).These help texts have a short general overview andbriefly explain the available command line options.

All runner scripts also support getting the version information withthe option--version. This information also contains Pythonversion and the platform type:

$ robot --versionRobot Framework 7.0 (Python 3.12.1 on darwin)C:\>rebot --versionRebot 6.1.1 (Python 3.11.0 on win32)

3.1.6   Creating start-up scripts

Test cases are often executed automatically by a continuousintegration system or some other mechanism. In such cases, there is aneed to have a script for starting the test execution, and possiblyalso for post-processing outputs somehow. Similar scripts are alsouseful when running tests manually, especially if a large number ofcommand line options are needed or setting up the test environment iscomplicated.

In UNIX-like environments, shell scripts provide a simple but powerfulmechanism for creating custom start-up scripts. Windows batch filescan also be used, but they are more limited and often also morecomplicated. A platform-independent alternative is using Python orsome other high-level programming language. Regardless of thelanguage, it is recommended that long option names are used, becausethey are easier to understand than the short names.

Shell script example

In this example, the same web tests in thelogin directory are executedwith different browsers and the results combined afterwards usingRebot.The script also accepts command line options itself and simply forwards themto therobot command using the handy$* variable:

#!/bin/bashrobot--nameFirefox--variableBROWSER:Firefox--outputout/fx.xml--lognone--reportnone$*loginrobot--nameIE--variableBROWSER:IE--outputout/ie.xml--lognone--reportnone$*loginrebot--nameLogin--outputdirout--outputlogin.xmlout/fx.xmlout/ie.xml

Batch file example

Implementing the above shell script example using batch files is not verycomplicated either. Notice that arguments to batch files can be forwardedto executed commands using%*:

@echo offrobot --name Firefox --variable BROWSER:Firefox --output out\fx.xml --log none --report none%* loginrobot --name IE --variable BROWSER:IE --log none --output out\ie.xml --report none%* loginrebot --name Login --outputdir out --output login.xml out\fx.xml out\ie.xml

Note

Prior to Robot Framework 3.1robot andrebot commands wereimplemented as batch files on Windows and using them in anotherbatch file required prefixing the whole command withcall.

Python example

When start-up scripts gets more complicated, implementing them using shellscripts or batch files is not that convenient. This is especially true ifboth variants are needed and same logic needs to be implemented twice. Insuch situations it is often better to switch to Python. It is possible toexecute Robot Framework from Python using thesubprocess module, butoften using Robot Framework's ownprogrammatic API is more convenient.The easiest APIs to use arerobot.run_cli androbot.rebot_cli thataccept same command line arguments than therobot andrebot commands.

The following example implements the same logic as the earlier shell scriptand batch file examples. In Python arguments to the script itself areavailable insys.argv:

#!/usr/bin/env pythonimportsysfromrobotimportrun_cli,rebot_clicommon=['--log','none','--report','none']+sys.argv[1:]+['login']run_cli(['--name','Firefox','--variable','BROWSER:Firefox','--output','out/fx.xml']+common,exit=False)run_cli(['--name','IE','--variable','BROWSER:IE','--output','out/ie.xml']+common,exit=False)rebot_cli(['--name','Login','--outputdir','out','out/fx.xml','out/ie.xml'])

Note

exit=False is needed because by defaultrun_cli exits tosystem with the correctreturn code.rebot_cli does that too,but in the above example that is fine.

3.1.7   Making*.robot files executable

On UNIX-like operating systems it is possible to make*.robotfiles executable by giving them execution permission and adding ashebanglike in this example:

#!/usr/bin/env robot*** Test Cases ***ExampleLog to consoleExecuting!

If the above content would be in a fileexample.robot and that filewould be executable, it could be executed from the command line like below.Starting from Robot Framework 3.2, individually executed files can have anyextension, or no extension at all, so the same would work also if the filewould be named justexample.

./example.robot

This trick does not work when executing a directory but can be handy whenexecuting a single file. It is probably more often useful whenautomating tasks than when automating tests.

3.1.8   Debugging problems

A test case can fail because the system under test does not workcorrectly, in which case the test has found a bug, or because the testitself is buggy. The error message explaining the failure is shown onthecommand line output and in thereport file, and sometimesthe error message alone is enough to pinpoint the problem. More oftenthat not, however,log files are needed because they have alsoother log messages and they show which keyword actually failed.

When a failure is caused by the tested application, the error messageand log messages ought to be enough to understand what caused it. Ifthat is not the case, the test library does not provideenoughinformation and needs to be enhanced. In this situation running thesame test manually, if possible, may also reveal more informationabout the issue.

Failures caused by test cases themselves or by keywords they use cansometimes be hard to debug. If the error message, for example, tellsthat a keyword is used with wrong number of arguments fixing theproblem is obviously easy, but if a keyword is missing or fails inunexpected way finding the root cause can be harder. The first placeto look for more information is theexecution errors section inthe log file. For example, an error about a failed test library importmay well explain why a test has failed due to a missing keyword.

If the log file does not provide enough information by default, it ispossible to execute tests with a lowerlog level. For exampletracebacks showing where in the code the failure occurred are loggedusing theDEBUG level, and this information is invaluable whenthe problem is in an individual library keyword.

Logged tracebacks do not contain information about methods inside RobotFramework itself. If you suspect an error is caused by a bug in the framework,you can enable showing internal traces by setting environment variableROBOT_INTERNAL_TRACES to any non-empty value.

If the log file still does not have enough information, it is a goodidea to enable thesyslog and see what information it provides. It isalso possible to add some keywords to the test cases to see what isgoing on. EspeciallyBuiltIn keywordsLog andLogVariables are useful. If nothing else works, it is always possible tosearch help frommailing lists or elsewhere.

Using the Python debugger (pdb)

It is also possible to use thepdb module from the Python standardlibrary to set a break point and interactively debug a running test.The typical way of invoking pdb by inserting:

importpdb;pdb.set_trace()

at the location you want to break into debugger will not work correctlywith Robot Framework, as the standard output stream isredirected during keyword execution. Instead, you can use the following:

importsys,pdb;pdb.Pdb(stdout=sys.__stdout__).set_trace()

from within a python library or alternatively:

Evaluatepdb.Pdb(stdout=sys.__stdout__).set_trace()modules=sys, pdb

can be used directly in a test case.

3.2   Test execution

This section describes how the test suite structure created from the parsedtest data is executed, how test status is determined, and how to continueexecuting a test case if there are failures, and how to stop the whole testexecution gracefully.

3.2.1   Execution flow

Executed suites and tests

Test cases are always executed within a test suite. A test suitecreated from asuite file has tests directly, whereas suitescreated fromdirectories have child test suites which either havetests or their own child suites. By default all the tests in anexecuted suite are run, but it is possible toselect tests usingoptions--test,--suite,--include and--exclude. Suites containing no tests are ignored.

The execution starts from the top-level test suite. If the suite hastests they are executed one-by-one, and if it has suites they areexecuted recursively in depth-first order. When an individual testcase is executed, the keywords it contains are run in asequence. Normally the execution of the current test ends if anyof the keywords fails, but it is also possible tocontinue after failures. The exactexecution order and howpossiblesetups and teardowns affect the execution are discussedin the following sections.

Setups and teardowns

Setups and teardowns can be used ontest suite,test case anduser keyword levels.

Suite setup

If a test suite has a setup, it is executed before its tests and childsuites. If the suite setup passes, test execution continuesnormally. If it fails, all the test cases the suite and its childsuites contain are marked failed. The tests and possible suite setupsand teardowns in the child test suites are not executed.

Suite setups are often used for setting up the test environment.Because tests are not run if the suite setup fails, it is easy to usesuite setups for verifying that the environment is in state in which thetests can be executed.

Suite teardown

If a test suite has a teardown, it is executed after all its testcases and child suites. Suite teardowns are executed regardless of thetest status and even if the matching suite setup fails. If the suiteteardown fails, all tests in the suite are marked failed afterwards inreports and logs.

Suite teardowns are mostly used for cleaning up the test environmentafter the execution. To ensure that all these tasks are done,all thekeywords used in the teardown are executed even if some of themfail.

Test setup

Possible test setup is executed before the keywords of the test case.If the setup fails, the keywords are not executed. The main usefor test setups is setting up the environment for that particular testcase.

Test teardown

Possible test teardown is executed after the test case has beenexecuted. It is executed regardless of the test status and alsoif test setup has failed.

Similarly as suite teardown, test teardowns are used mainly forcleanup activities. Also they are executed fully even if some of theirkeywords fail.

User keyword setup

User keyword setup is executed before the keyword body. If the setup fails,the body is not executed. There is not much difference between the keywordsetup and the first keyword in the body.

Note

User keyword setups are new in Robot Framework 7.0.

User keyword teardown

User keyword teardown is run after the keyword is executed otherwise, regardlessthe status. User keyword teardowns are executed fully even if some of theirkeywords would fail.

Execution order

Test cases in a test suite are executed in the same order as they are definedin the test case file. Test suites inside a higher level test suite areexecuted in case-insensitive alphabetical order based on the file or directoryname. If multiple files and/or directories are given from the command line,they are executed in the order they are given.

If there is a need to use certain test suite execution order inside adirectory, it is possible to add prefixes like01 and02 into file and directory names. Such prefixes are notincluded in the generated test suite name if they are separated fromthe base name of the suite with two underscores:

01__my_suite.robot -> My Suite02__another_suite.robot -> Another Suite

If the alphabetical ordering of test suites inside suites isproblematic, a good workaround is giving them separately in therequired order. This easily leads to overly long start-up commands,butargument files allow listing files nicely one file per line.

It is also possible torandomize the execution order usingthe--randomize option.

3.2.2   Test and suite statuses

This section explains how tests can getPASS,FAIL orSKIP status and how thesuite status is determined based on test statuses.

Note

The SKIP status is new in Robot Framework 4.0.

PASS

A test gets the PASS status if it is executed and none of the keywords it contains fails.

Prematurely passing tests

Normally all keywords are executed, but it is also possible to useBuiltIn keywordsPass Execution andPass Execution If to stopexecution with the PASS status and not run the remaining keywords.

HowPass Execution andPass Execution If behavein different situations is explained below:

  • When used in anysetup or teardown (suite, test or keyword), thesekeywords pass that setup or teardown. Possible teardowns of the startedkeywords are executed. Test execution or statuses are not affected otherwise.
  • When used in a test case outside setup or teardown, the keywords pass thatparticular test case. Possible test and keyword teardowns are executed.
  • Possiblecontinuable failures that occur before these keyword are used,as well as failures in teardowns executed afterwards, will fail the execution.
  • It is mandatory to give an explanation messagewhy execution was interrupted, and it is also possible tomodify test case tags. For more details, and usage examples, see thedocumentation of these keywords.

Passing execution in the middle of a test, setup or teardown should beused with care. In the worst case it leads to tests that skip all theparts that could actually uncover problems in the tested application.In cases where execution cannot continue do to external factors,it is often safer toskip the test.

FAIL

The most common reason for a test to get the FAIL status is that one of the keywordsit contains fails. The keyword itself can fail byraising an exception or thekeyword can be called incorrectly. Other reasons for failures include syntax errorsand the test being empty.

If asuite setup fails, tests in that suite are marked failed without running them.If asuite teardown fails, tests are marked failed retroactively.

SKIP

Starting from Robot Framework 4.0, tests can get also SKIP status in addition toPASS and FAIL. There are many different ways to get this status.

Skipping before execution

The command line option--skip can be used to skip specified tests withoutrunning them at all. It works based ontags and supportstag patterns likeexamp?? andtagANDanother. If it is used multiple times, all tests matching any ofspecified tags or tag patterns are skipped:

--skip require-network--skip windowsANDversion9?--skip python2.* --skip python3.[0-6]

Tests can also be skipped by tagging the test with therobot:skipreserved tag.This tag can also be set using a variable, which allows skipping test dynamicallyduring execution.

*** Variables ***${SKIP}robot:skip*** Test Cases ***Literal   [Documentation]Unconditionally skipped.   [Tags]robot:skipLogThis is not executedAs variable   [Documentation]Skipped unless${SKIP} is set to a different value.   [Tags]    ${SKIP}LogThis is not executed by default

The difference between--skip and--exclude is that withthe latter tests areomitted from the execution altogether and they will notbe shown in logs and reports. With the former they are included, but not actuallyexecuted, and they will be visible in logs and reports.

Note

robot:skip is new in Robot Framework 5.0.

Note

Support for using variables with tags used for skipping is new inRobot Framework 7.2.

Skipping dynamically during execution

Tests can get the skip status during execution in various ways:

  • Using theBuiltIn keywordSkip anywhere in the test case, including setup orteardown. UsingSkip keyword has two effects: the test gets the SKIP statusand rest of the test is not executed. However, if the test has a teardown, it will berun.
  • Using theBuiltIn keywordSkip If which takes a condition and skips the testif the condition is true.
  • Library keywords may also trigger skip behavior by using a special exceptions.This is explained theSkipping tests section in theCreating test librarieschapter.
  • Ifsuite setup is skipped using any of the above means, all tests in the suiteare skipped without executing them.
  • Ifsuite teardown is skipped, all tests will be marked skipped retroactively.
Automatically skipping failed tests

The command line option--skiponfailure can be used to automatically markfailed tests skipped. It works based ontags and supportstag patterns likethe--skip option discussed above:

--skiponfailure not-ready--skiponfailure experimentalANDmobile

Starting from RF 5.0, the reserved tagrobot:skip-on-failure can alternatively be used toachieve the same effect as above:

*** Test Cases ***Example    [Tags]robot:skip-on-failureFailthis test will be marked as skipped instead of failed

The motivation for this functionality is allowing execution of tests that are not yetready or that are testing a functionality that is not yet ready. Instead of such testsfailing, they will be marked skipped and their tags can be used to separate themfrom possible other skipped tests.

Migrating from criticality to SKIP

Earlier Robot Framework versions supported criticality concept that allowed markingtests critical or non-critical. By default all tests were critical, but the--critical and--noncritical options could be used to configure that.The difference between critical and non-critical tests was that non-critical testswere not included when determining the final status for an executed test suite orfor the whole test run. In practice the test status was two dimensional havingPASS and FAIL in one axis and criticality on the other.

Non-critical failed tests were in many ways similar to the current skipped tests.Because these features are similar and having both SKIP and criticality wouldhave created strange test statuses like non-critical SKIP, the criticality conceptwas removed in Robot Framework 4.0 when the SKIP status was introduced. The problemswith criticality are explained in more detail in theissue that proposed removing it.

The main use case for the criticality concept was being able to run tests thatare not yet ready or that are testing a functionality that is not yet ready. Thisuse case is nowadays covered by the skip-on-failure functionality discussed inthe previous section.

To ease migrating from criticality to skipping, the old--noncriticaloption worked as an alias for the new--skiponfailure in Robot Framework 4.0and also the old--critical option was preserved. Both old optionswere deprecated and they were removed in Robot Framework 5.0.

Suite status

Suite status is determined solely based on statuses of the tests it contains:

  • If any test has failed, suite status is FAIL.
  • If there are no failures but at least one test has passed, suite status is PASS.
  • If all tests have been skipped or the are no tests at all, suite status is SKIP.

3.2.3   Continuing on failure

Normally test cases are stopped immediately when any of their keywordsfail. This behavior shortens test execution time and preventssubsequent keywords hanging or otherwise causing problems if thesystem under test is in unstable state. This has a drawback that oftensubsequent keywords would give more information about the state of thesystem, though, and in some cases those subsequent keywords would actuallytake care of the needed cleanup activities. Hence Robot Framework offersseveral features to continue even if there are failures.

Execution continues on teardowns automatically

To make it sure that all the cleanup activities are taken care of, thecontinue-on-failure mode is automatically enabled insuite, test and keywordteardowns. In practice this means that in teardowns all thekeywords in all levels are always executed.

If this behavior is not desired, the specialrobot:stop-on-failure androbot:recursive-stop-on-failure tags can be used todisable it.

All top-level keywords are executed when tests have templates

When usingtest templates, all the top-level keywords are executed tomake it sure that all the different combinations are covered. In thisusage continuing is limited to the top-level keywords, and inside themthe execution ends normally if there are non-continuable failures.

*** Test Cases ***Continue with templates    [Template]Should be Equalthisfailsthisis run

If this behavior is not desired, the specialrobot:stop-on-failure androbot:recursive-stop-on-failure tags can be used todisable it.

Special failures from keywords

Library keywords report failures using exceptions, and it ispossible to use special exceptions to tell Robot Framework thatexecution can continue regardless the failure. How these exceptionscan be created is explained in theContinuable failures section intheCreating test libraries section.

When a test ends and there have been continuable failures,the test will be marked failed. If there are more than one failure,all of them will be enumerated in the final error message:

Several failures occurred:1) First error message.2) Second error message.

Test execution ends also if a normal failure occurs after a continuablefailure. Also in that case all the failures will be listed in thefinal error message.

The return value from failed keywords, possibly assigned to avariable, is always the PythonNone.

Run Keyword And Continue On Failure keyword

BuiltIn keywordRun Keyword And Continue On Failure allowsconverting any failure into a continuable failure. These failures arehandled by the framework exactly the same way as continuable failuresoriginating from library keywords discussed above.

*** Test Cases ***ExampleRun Keyword and Continue on FailureShould be Equal12LogThis is executed but test fails in the end

Enabling continue-on-failure using tags

All keywords executed as part of test cases or user keywords which aretagged with therobot:continue-on-failure tag are considered continuableby default. For example, the following two tests behave identically:

*** Test Cases ***Test 1Run Keyword and Continue on FailureShould be Equal12User Keyword 1Test 2    [Tags]robot:continue-on-failureShould be Equal12User Keyword 2*** Keywords ***User Keyword 1Run Keyword and Continue on FailureShould be Equal34LogThis is executedUser Keyword 2    [Tags]robot:continue-on-failureShould be Equal34LogThis is executed

These tags also affect the continue-on-failure mode with differentcontrolstructures. For example, the below test case will execute theDo Something keyword ten times regardless does it succeed or not:

*** Test Cases ***Example    [Tags]robot:continue-on-failureFOR    ${index}IN RANGE10Do SomethingEND

Settingrobot:continue-on-failure within a test case or a user keywordwill not propagate the continue-on-failure behavior into user keywordsthey call. If such recursive behavior is needed, therobot:recursive-continue-on-failure tag can be used. For example, allkeywords in the following example are executed:

*** Test Cases ***Example    [Tags]robot:recursive-continue-on-failureShould be Equal12User Keyword 1LogThis is executed*** Keywords ***User Keyword 1Should be Equal34User Keyword 2LogThis is executedUser Keyword 2Should be Equal56LogThis is executed

Settingrobot:continue-on-failure orrobot:recursive-continue-on-failure in atest case does NOT alter the behaviour of a failure in the keyword(s) executedas part of the[Setup]: The test case is marked as failed and notest case keywords are executed.

Note

Therobot:continue-on-failure androbot:recursive-continue-on-failuretags are new in Robot Framework 4.1. They do not work properly withWHILE loops prior to Robot Framework 6.0.

Disabling continue-on-failure using tags

Special tagsrobot:stop-on-failure androbot:recursive-stop-on-failurecan be used to disable the continue-on-failure mode if needed. They workwhencontinue-on-failure has been enabled using tags and also withteardowns andtemplates:

*** Test Cases ***Disable continue-in-failure set using tags    [Tags]robot:recursive-continue-on-failureKeywordKeyword# This is executedDisable continue-in-failure in teardownNo Operation    [Teardown]KeywordDisable continue-in-failure with templates    [Tags]robot:stop-on-failure    [Template]Should be Equalthisfailsthisis not run*** Keywords ***Keyword    [Tags]robot:stop-on-failureShould be EqualthisfailsShould be Equalthisis not run

Therobot:stop-on-failure tag affects only test cases and user keywordswhere it is used and does not propagate to user keywords they call nor totheir own teardowns. If recursive behavior affecting all called user keywordsand teardowns is desired, therobot:recursive-stop-on-failure tag can beused instead. If there is a need, its effect can again be disabled in lowerlevel keywords by usingrobot:continue-on-failure orrobot:recursive-continue-on-failure tags.

Therobot:stop-on-failure androbot:recursive-stop-on-failure tags do notalter the behavior of continuable failures caused bylibrary keywords orbyRun Keyword And Continue On Failure. For example, both keywords in thisexample are run even thoughrobot:stop-on-failure is used:

*** Test Cases ***Example    [Tags]robot:stop-on-failureRun Keyword and Continue on FailureShould be Equal12LogThis is executed regardless the tag

Ifrobot:recursive-stop-on-failure androbot:continue-on-failure are usedtogether in the same test or keyword, execution is stopped in called keywordsif there are failures, but continues in the test or keyword using these tags.Ifrobot:recursive-continue-on-failure androbot:stop-on-failure are usedtogether in the same test or keyword, execution is continued in called keywordsif there are failures, but stopped in the test or keyword using these tags.

Note

Therobot:stop-on-failure androbot:recursive-stop-on-failuretags are new in Robot Framework 6.0.

Note

Using recursive and non-recursive tags together in same test orkeyword is new in Robot Framework 7.0.

TRY/EXCEPT

Robot Framework 5.0 introduced nativeTRY/EXCEPT syntax that can be used forhandling failures:

*** Test Cases ***ExampleTRYSome KeywordEXCEPTExpected error messageError Handler KeywordEND

For more details see the separateTRY/EXCEPT syntax section.

BuiltIn keywords

There are severalBuiltIn keywords that can be used to execute other keywordsso that execution can continue after possible failures:

  • Run Keyword And Expect Error executes a keyword and expects it to failwith the specified error message. The aforementionedTRY/EXCEPT syntax isnowadays generally recommended instead.
  • Run Keyword And Ignore Error executes a keyword and silences possibleerror. It returns the status along with possible keyword return value orerror message. TheTRY/EXCEPT syntax generally works better in this caseas well.
  • Run Keyword And Warn On Failure is a wrapper forRun Keyword And Ignore Error that automatically logs a warningif the executed keyword fails.
  • Run Keyword And Return Status executes a keyword and returns BooleanTrue orFalse depending on did it pass or fail.

3.2.4   Stopping test execution gracefully

Sometimes there is a need to stop the test execution before all the testshave finished, but so that logs and reports are created. Different ways howto accomplish this are explained below. In all these cases the remainingtest cases are marked failed.

The tests that are automatically failed getrobot:exit tag andthe generated report will includeNOT robot:exitcombined tag patternto easily see those tests that were not skipped. Note that the test in whichthe exit happened does not get therobot:exit tag.

Note

Prior to Robot Framework 3.1, the special tag was namedrobot-exit.

PressingCtrl-C

The execution is stopped whenCtrl-C is pressed in the consolewhere the tests are running. The execution is stopped immediately,but reports and logs are still generated.

IfCtrl-C is pressed again, the execution ends immediately andreports and logs are not created.

Using signals

On UNIX-like machines it is possible to terminate test executionusing signalsINT andTERM. These signals can be sentfrom the command line usingkill command, and sending signals canalso be easily automated.

Using keywords

The execution can be stopped also by the executed keywords. There is aseparateFatal ErrorBuiltIn keyword for this purpose, andcustom keywords can usefatal exceptions when they fail.

Stopping when first test case fails

If option--exitonfailure (-X) is used, the whole execution stopsimmediately if any test fails.

Stopping usingrobot:exit-on-failure tag

If a failed test has aspecialrobot:exit-on-failure tag, the whole executionstops immediately after that test.

Note

This functionality is new in Robot Framework 7.2.

Stopping on parsing or execution error

Robot Framework separatesfailures caused by failing keywords fromerrorscaused by, for example, invalid settings or failed test library imports.By default these errors are reported astest execution errors, but errorsthemselves do not fail tests or affect execution otherwise. If--exitonerror option is used, however, all such errors are consideredfatal and execution stopped so that remaining tests are marked failed. Withparsing errors encountered before execution even starts, this means that notests are actually run.

Note

Also logging something with theERRORlog level is consideredan error and stops the execution if the--exitonerror optionis used.

Handling teardowns

By default teardowns of the tests and suites that have been started areexecuted even if the test execution is stopped using one of the methodsabove. This allows clean-up activities to be run regardless how executionends.

It is also possible to skip teardowns when execution is stopped by using--skipteardownonexit option. This can be useful if, for example,clean-up tasks take a lot of time.

3.3   Task execution

Robot Framework can be used also for other automation purposes than testautomation, and starting from Robot Framework 3.1 it is possible toexplicitlycreate and execute tasks. For most parts task executionand test execution work the same way, and this section explains thedifferences.

3.3.1   Generic automation mode

When Robot Framework is used execute a file and it notices that the filehas tasks, not tests, it automatically sets itself into the generic automationmode. This mode does not change the actual execution at all, but whenlogs and reports are created, they use termtask, nottest. They have,for example, headers likeTask Log andTask Statistics instead ofTest Log andTest Statistics.

The generic automation mode can also be enabled by using the--rpaoption. In that case the executed files can have either tests or tasks.Alternatively--norpa can be used to force the test automationmode even if executed files contain tasks. If neither of these options areused, it is an error to execute multiple files so that some have tests andothers have tasks.

The execution mode is stored in the generatedoutput file and read byRebot if outputs are post-processed. The mode can alsobe set whenusing Rebot if necessary.

3.3.2   Task related command line options

All normal command line options can be used when executing tasks. If thereis a need toselect only certain tasks for execution,--taskcan be used instead of--test. Additionally the aforementioned--rpa can be used to control the execution mode.

3.4   Post-processing outputs

XML output files that are generated during the test execution can bepost-processed afterwards by the Rebot tool, which is an integralpart of Robot Framework. It is used automatically when testreports and logs are generated during the test execution, and using itseparately allows creating custom reports and logs as well as combiningand merging results.

3.4.1   Using Rebot

Synopsis

rebot [options] outputspython -m robot.rebot [options] outputspython path/to/robot/rebot.py [options] outputs

The most common way to use Rebot is using therebot command.Alternatively it is possible to execute the installedrobot.rebotmodule or therobot/rebot.py file using the selected Pythoninterpreter.

Specifying options and arguments

The basic syntax for using Rebot is exactly the same as whenstarting test execution and also most of the command line options areidentical. The main difference is that arguments to Rebot areXML output files instead of test data files or directories.

Return codes with Rebot

Return codes from Rebot are exactly same as whenrunning tests.

Controlling execution mode

Rebot notices havetests ortasks been run, and by default preserves theexecution mode. The mode affects logs and reports so that in the former casethey will use termtest likeTest Log andTest Statistics, and inthe latter case termtask likeTask Log andTask Statistics.

Rebot also supports using--rpa or--norpa options to setthe execution mode explicitly. This is necessary if multiple output filesare processed and they have conflicting modes.

3.4.2   Creating reports, logs and output files

You can use Rebot for creating the same reports and logs thatare created automatically during the test execution. Of course, it isnot sensible to create the exactly same files, but, for example,having one report with all test cases and another with only somesubset of tests can be useful:

rebot output.xmlrebot path/to/output_file.xmlrebot --include smoke --name Smoke_Tests c:\results\output.xml

Another common usage is creating only the output file when running tests(log and report generation can be disabled with--log NONE--report NONE) and generating logs and reports later. Tests can,for example, be executed on different environments, output files collectedto a central place, and reports and logs created there.

Rebot does not create XML output files by default, but it is possible tocreate them by using the--output (-o) option. Log and reportare created by default, but they can be disabled by using valueNONE(case-insensitive) if they are not needed:

rebot --include smoke --output smoke.xml --log none --report none original.xml

3.4.3   Combining outputs

An important feature in Rebot is its ability to combineoutputs from different test execution rounds. This capability allows,for example, running the same test cases on different environments andgenerating an overall report from all outputs. Combining outputs isextremely easy, all that needs to be done is giving several outputfiles as arguments:

rebot output1.xml output2.xmlrebot outputs/*.xml

When outputs are combined, a new top-level test suite is created sothat test suites in the given output files are its child suites. Thisworks the same way whenmultiple test data files or directories areexecuted, and also in this case the name of the top-level testsuite is created by joining child suite names with an ampersand (&)and spaces. These automatically generated names are not that good, andit is often a good idea to use--name to give a moremeaningful name:

rebot --name Browser_Compatibility firefox.xml opera.xml safari.xml ie.xmlrebot --include smoke --name Smoke_Tests c:\results\*.xml

3.4.4   Merging outputs

If same tests are re-executed or a single test suite executed in pieces,combining results like discussed above creates an unnecessary top-leveltest suite. In these cases it is typically better to merge results instead.Merging is done by using--merge (-R) option which changes the way howRebot combines two or more output files. This option itself takes noarguments and all other command line options can be used with it normally:

rebot --merge original.xml merged.xmlrebot --merge --name Example first.xml second.xml third.xml

When suites are merged, documentation, suite setup and suite teardown are gotfrom the last merged suite. Suite metadata from all merged suites is preservedso that values in latter suites have precedence.

How merging tests works is explained in the following sections discussingthe two main merge use cases.

Note

Getting suite documentation and metadata from merged suites is new inRobot Framework 6.0.

Merging re-executed tests

There is often a need to re-execute a subset of tests, for example, afterfixing a bug in the system under test or in the tests themselves. This can beaccomplished byselecting test cases by names (--test and--suite options), tags (--include and--exclude),or by previous status (--rerunfailed or--rerunfailedsuites).

Combining re-execution results with the original results using the defaultcombining outputs approach does not work too well. The main problem isthat you get separate test suites and possibly already fixed failures arealso shown. In this situation it is better to use--merge (-R)option to tell Rebot to merge the results instead. In practice thismeans that tests from the latter test runs replace tests in the original.An exception to this rule is thatskipped tests in latter runs are ignoredand original tests preserved.

This usage is best illustrated by a practical example using--rerunfailed and--merge together:

robot --output original.xml tests                          # first execute all testsrobot --rerunfailed original.xml --output rerun.xml tests  # then re-execute failingrebot --merge original.xml rerun.xml                       # finally merge results

The message of the merged tests contains a note that results have beenreplaced. The message also shows the old status and message of the test.

Merged results must always have same top-level test suite. Tests and suitesin merged outputs that are not found from the original output are added intothe resulting output. How this works in practice is discussed in the nextsection.

Note

Ignoring skipped tests in latter runs is new in Robot Framework 4.1.

Merging suites executed in pieces

Another important use case for the--merge option is merging resultsgot when running a test suite in pieces using, for example,--includeand--exclude options:

robot --include smoke --output smoke.xml tests   # first run some testsrobot --exclude smoke --output others.xml tests  # then run othersrebot --merge smoke.xml others.xml               # finally merge results

When merging outputs like this, the resulting output contains all tests andsuites found from all given output files. If some test is found from multipleoutputs, latest results replace the earlier ones like explained in the previoussection. Also this merging strategy requires the top-level test suites tobe same in all outputs.

3.4.5   JSON output files

Rebot can create and process output files also in theJSON format.Creating JSON output files is done using the normal--output optionso that the specified file has a.json extension:

rebot --output output.json output.xml

When reading output files, JSON files are automatically recognized bythe extension:

rebot output.jsonrebot output1.json output2.json

When combining or merging results, it is possible to mix JSON and XML output files:

rebot output1.xml output2.jsonrebot --merge original.xml rerun.json

The JSON output file structure is documented in theresult.jsonschema file.

Note

Support for JSON output files is new in Robot Framework 7.0.Prior to Robot Framework 7.2 JSON output files contained onlyinformation about the executed suite, but nowadays they containthe same result data asXML output files.

3.5   Configuring execution

This section explains different command line options that can be usedfor configuring thetest execution orpost-processingoutputs. Options related to generatedoutput files are discussed inthe next section.

3.5.1   Selecting files to parse

Executing individual files

When executing individual files, Robot Framework tries to parse and run themregardless the name or the file extension. What parser to use dependson the extension:

Examples:

robot example.robot    # Standard Robot Framework parser.robot example.tsv      # Must be compatible with the standard parser.robot example.rst      # reStructuredText parser.robot x.robot y.rst    # Parse both files using an appropriate parser.

Included and excluded files

When executing adirectory, files and directories are parsed usingthe following rules:

  • All files and directories starting with a dot (.) or an underscore(_) are ignored.
  • .robot files are parsed using the normalRobot Framework parser.
  • .robot.rst files are parsed using thereStructuredText parser.
  • .rbt files are parsed using theJSON parser.
  • Files supported bycustom parsers are parsed by a matching parser.
  • Other files are ignored unless parsing them has been enabled by usingthe--parseinclude or--extension options discussedin the subsequent sections.

Selecting files by name or path

When executing a directory, it is possible to parse only certain files based ontheir name or path by using the--parseinclude (-I) option. This optionhas slightly different semantics depending on the value it is used with:

  • If the value is just a file name likeexample.robot, files matchingthe name in all directories will be parsed.
  • To match only a certain file in a certain directory, files can be givenas relative or absolute paths likepath/to/tests.robot.
  • If the value is a path to a directory, all files inside that directory are parsed,recursively.

Examples:

robot --parseinclude example.robot tests       # Parse `example.robot` files anywhere under `tests`.robot -I example_*.robot -I ???.robot tests    # Parse files matching `example_*.robot` or `???.robot` under `tests`.robot -I tests/example.robot tests             # Parse only `tests/example.robot`.robot --parseinclude tests/example tests       # Parse files under `tests/example` directory, recursively.

Values used with--parseinclude are case-insensitive and supportglob patterns likeexample_*.robot. There are, however,two small differences compared to how patterns typically work with Robot Framework:

  • * matches only a single path segment. For example,path/*/tests.robotmatchespath/to/tests.robot but notpath/to/nested/tests.robot.
  • ** can be used to enable recursive matching. For example,path/**/tests.robotmatches bothpath/to/tests.robot andpath/to/nested/tests.robot.

If the pattern contains an extension, files with that extension are parsedeven if they bydefault would not be. What parser to use depends onthe used extension:

Notice that when you use a pattern like*.robot and there exists a file thatmatches the pattern in the execution directory, the shell may resolvethe pattern before Robot Framework is called and the value passed toit is the file name, not the original pattern. In such cases you needto quote or escape the pattern like'*.robot' or\*.robot.

Note

--parseinclude is new in Robot Framework 6.1.

Selecting files by extension

In addition to using the--parseinclude option discussed in theprevious section, it is also possible to enable parsing files that arenotparsed by default by using the--extension (-F) option.Matching extensions is case insensitive and the leading dot can be omitted.If there is a need to parse more than one kind of files, it is possible touse a colon: to separate extensions:

robot --extension rst path/to/tests    # Parse only *.rst files.robot -F robot:rst path/to/tests       # Parse *.robot and *.rst files.

The above is equivalent to the following--parseinclude usage:

robot --parseinclude *.rst path/to/testsrobot -I *.robot -I *.rst path/to/tests

Because the--parseinclude option is more powerful and covers allsame use cases as the--extension option, the latter is likely to bedeprecated in the future. Users are recommended to use--parseincludealready now.

Using custom parsers

External parsers can parse files that Robot Framework does not recognizeotherwise. For more information about creating and using such parsers seetheParser interface section.

3.5.2   Selecting test cases

Robot Framework offers several command line options for selectingwhich test cases to execute. The same options work also whenexecutingtasks and when post-processing outputs withRebot.

By test names

The easiest way to select only some tests to be run is using the--test (-t) option. As the name implies, it can be used forselecting tests by their names. Given names are case, space and underscoreinsensitive and they also supportsimple patterns. The option can beused multiple times to match multiple tests:

--test Example                   # Match only tests with name 'Example'.--test example*                  # Match tests starting with 'example'.--test first --test second       # Match tests with name 'first' or 'second'.

To pinpoint a test more precisely, it is possible to prefix the test namewith a suite name:

--test mysuite.mytest            # Match test 'mytest' in suite 'mysuite'.--test root.sub.test             # Match test 'test' in suite 'sub' in suite 'root'.--test *.sub.test                # Match test 'test' in suite 'sub' anywhere.

Notice that when the given name includes a suite name, it must match the wholesuite name starting from the root suite. Using a wildcard as in the last exampleabove allows matching tests with a parent suite anywhere.

Using the--test option is convenient when only a few tests needsto be selected. A common use case is running just the test that is currentlybeing worked on. If a bigger number of tests needs to be selected,it is typically easier to select themby suite names orby tag names.

Whenexecuting tasks, it is possible to use the--task optionas an alias for--test.

By suite names

Tests can be selected also by suite names with the--suite (-s)option that selects all tests in matching suites. Similarlyas with--test, given names are case, space and underscoreinsensitive and supportsimple patterns. To pinpoint a suitemore precisely, it is possible to prefix the name with the parent suitename:

--suite Example                  # Match only suites with name 'Example'.--suite example*                 # Match suites starting with 'example'.--suite first --suite second     # Match suites with name 'first' or 'second'.--suite root.child               # Match suite 'child' in root suite 'root'.--suite *.parent.child           # Match suite 'child' with parent 'parent' anywhere.

If the name contains a parent suite name, it must match the whole suite namethe same way as with--test. Using a wildcard as in the last exampleabove allows matching suites with a parent suite anywhere.

Note

Prior to Robot Framework 7.0,--suite with a parent suitedid not need to match the whole suite name. For example,parent.childwould match suitechild with parentparent anywhere. The name mustbe prefixed with a wildcard if this behavior is desired nowadays.

If both--suite and--test options are used, only thespecified tests in specified suites are selected:

--suite mysuite --test mytest    # Match test 'mytest' if its inside suite 'mysuite'.

Using the--suite option is more or less the same as executingthe appropriate suite file or directory directly. The main difference isthat if a file or directory is run directly, possible suite setups and teardownson higher level are not executed:

# Root suite is 'Tests' and its possible setup and teardown are run.robot --suite example path/to/tests# Root suite is 'Example' and possible higher level setups and teardowns are ignored.robot path/to/tests/example.robot

Prior to Robot Framework 6.1, files not matching the--suite optionwere not parsed at all for performance reasons. This optimization was notpossible anymore after suites got a newName setting that can overridethe default suite name that is got from the file or directory name. New--parseinclude option has been added toexplicitly select whichfiles are parsed if this kind of parsing optimization is needed.

By tag names

It is possible to include and exclude test cases bytag names with the--include (-i) and--exclude (-e) options, respectively.If the--include option is used, only test cases having a matchingtag are selected, and with the--exclude option test cases having amatching tag are not. If both are used, only tests with a tagmatching the former option, and not with a tag matching the latter,are selected:

--include example--exclude not_ready--include regression --exclude long_lasting

Both--include and--exclude can be used severaltimes to match multiple tags. In that case a test is selectedif it has a tag that matches any included tags, and also has no tagthat matches any excluded tags.

In addition to specifying a tag to match fully, it is possible to usetag patterns where* and? are wildcards andAND,OR, andNOT operators can be used forcombining individual tags or patterns together:

--include feature-4?--exclude bug*--include fooANDbar--exclude xxORyyORzz--include fooNOTbar

Another way to exclude tests by tags is using therobot:excludereserved tag.This tag can also be set using a variable, which allows excluding testdynamically during execution.

*** Variables ***${EXCLUDE}robot:exclude*** Test Cases ***Literal   [Documentation]Unconditionally excluded.   [Tags]robot:excludeLogThis is not executedAs variable   [Documentation]Excluded unless${EXCLUDE} is set to a different value.   [Tags]    ${EXCLUDE}LogThis is not executed by default

Selecting test cases by tags is a very flexible mechanism and allowsmany interesting possibilities:

  • A subset of tests to be executed before other tests, often called smoketests, can be tagged withsmoke and executed with--include smoke.
  • Unfinished test can be committed to version control with a tag such asnot_ready and excluded from the test execution with--exclude not_ready.
  • Tests can be tagged withsprint-<num>, where<num> specifies the number of the current sprint, andafter executing all test cases, a separate report containing onlythe tests for a certain sprint can be generated (for example,rebot--include sprint-42 output.xml).

Options--include and--exclude can be used in combinationwith--suite and--test discussed in the previous section.In that case tests that are selected must match all selection criteria:

--suite example --include tag    # Match test if it is in suite 'example' and has tag 'tag'.--suite example --exclude tag    # Match test if it is in suite 'example' and does not have tag 'tag'.--test ex* --include tag         # Match test if its name starts with 'ex' and it has tag 'tag'.--test ex* --exclude tag         # Match test if its name starts with 'ex' and it does not have tag 'tag'.

Note

robot:exclude is new in Robot Framework 5.0.

Note

Using variables withrobot:exclude is new in Robot Framework 7.2.Using variables with tags matched against--include and--exclude is not supported.

Note

In Robot Framework 7.0--include and--test were cumulativeand selected tests needed to match only either of these options. That behaviorcausedbackwards incompatibility problems and it was reverted already inRobot Framework 7.0.1.

Re-executing failed test cases

Command line option--rerunfailed (-R) can be used to select all failedtests from an earlieroutput file for re-execution. This option is useful,for example, if running all tests takes a lot of time and one wants toiteratively fix failing test cases.

robot tests                             # first execute all testsrobot --rerunfailed output.xml tests    # then re-execute failing

Behind the scenes this option selects the failed tests as they would have beenselected individually using the--test option. It is possible to furtherfine-tune the list of selected tests by using--test,--suite,--include and--exclude options.

It is an error if the output contains no failed tests, but this behavior can bechanged by using the--runemptysuite optiondiscussed below.Using an output not originating from executing the same tests that are runnow causes undefined results. Using a special valueNONE as the output issame as not specifying this option at all.

Tip

Re-execution results and original results can bemerged togetherusing the--merge command line option.

Re-executing failed test suites

Command line option--rerunfailedsuites (-S) can be used to select allfailed suites from an earlieroutput file for re-execution. Like--rerunfailed (-R), this option is useful when full test executiontakes a lot of time. Note that all tests from a failed test suite will bere-executed, even passing ones. This option is useful when the tests ina test suite depends on each other.

Behind the scenes this option selects the failed suites as they would have beenselected individually with the--suite option. It is possible to furtherfine-tune the list of selected tests by using--test,--suite,--include and--exclude options.

When no tests match selection

By default when no tests match the selection criteria test execution failswith an error like:

[ ERROR ] Suite 'Example' contains no tests matching tag 'xxx'.

Because no outputs are generated, this behavior can be problematic if testsare executed and results processed automatically. Luckily a command lineoption--RunEmptySuite (case-insensitive) can be used to forcethe suite to be executed also in this case. As a result normal outputs arecreated but show zero executed tests. The same option can be used also toalter the behavior when an empty directory or a test case file containingno tests is executed.

Similar situation can occur also when processing output files withRebot.It is possible that no test match the used filtering criteria or thatthe output file contained no tests to begin with. By default executingRebot fails in these cases, but it has a separate--ProcessEmptySuite option that can be used to alter the behavior.In practice this option works the same way as--RunEmptySuite whenrunning tests.

Note

Using--RunEmptySuite with--ReRunFailedor--ReRunFailedSuites requires Robot Framework 5.0.1or newer.

3.5.3   Setting metadata

Setting suite name

When Robot Framework parses test data,suite names are createdfrom file and directory names. The name of the top-level test suitecan, however, be overridden with the command line option--name (-N):

robot --name "Custom name" tests.robot

Setting suite documentation

In addition todefining documentation in the test data, documentationof the top-level suite can be given from the command line with theoption--doc (-D). The value can contain simpleHTML formattingand must be quoted if it contains spaces.

If the given documentation is a relative or absolute path pointing to an existingfile, the actual documentation will be read from that file. This is especiallyconvenient if the externally specified documentation is long or contains multiplelines.

Examples:

robot --doc "Example documentation" tests.robotrobot --doc doc.txt tests.robot    # Documentation read from doc.txt if it exits.

Note

Reading documentation from an external file is new in Robot Framework 4.1.

Prior to Robot Framework 3.1, underscores in documentation wereconverted to spaces same way as with the--name option.

Setting free suite metadata

Free suite metadata may also be given from the command line with theoption--metadata (-M). The argument must be in the formatname:value, wherename the name of the metadata to set andvalue is its value. The value can contain simpleHTML formatting andthe whole argument must be quoted if it contains spaces.This option may be used several times to set multiple metadata values.

If the given value is a relative or absolute path pointing to an existingfile, the actual value will be read from that file. This is especiallyconvenient if the value is long or contains multiple lines.If the value should be a path to an existing file, not read from that file,the value must be separated with a space from thename: part.

Examples:

robot --metadata Name:Value tests.robotrobot --metadata "Another Name:Another value, now with spaces" tests.robotrobot --metadata "Read From File:meta.txt" tests.robot    # Value read from meta.txt if it exists.robot --metadata "Path As Value: meta.txt" tests.robot    # Value always used as-is.

Note

Reading metadata value from an external file is new in Robot Framework 4.1.

Prior to Robot Framework 3.1, underscores in the value wereconverted to spaces same way as with the--name option.

Setting test tags

The command line option--settag (-G) can be used to setthe given tag to all executed test cases. This option may be usedseveral times to set multiple tags.

3.5.4   Configuring where to search libraries and other extensions

When Robot Framework imports atest library,listener, or some otherPython based extension, it uses the Python interpreter to import the modulecontaining the extension from the system. The list of locations where modulesare looked for is calledthe module search path, and its contents can beconfigured using different approaches explained in this section.

Robot Framework uses Python's module search path also when importingresourceand variable files if the specified path does not match any file directly.

The module search path being set correctly so that libraries and otherextensions are found is a requirement for successful test execution. Ifyou need to customize it using approaches explained below, it is oftena good idea to create a customstart-up script.

Locations automatically in module search path

Python interpreters have their own standard library as well as a directorywhere third party modules are installed automatically in the module searchpath. This means that test librariespackaged using Python's own packagingsystem are automatically installed so that they can be imported withoutany additional configuration.

PYTHONPATH

Python reads additional locations to be added tothe module search path fromPYTHONPATH environment variables.If you want to specify more than one location in any of them, youneed to separate the locations with a colon on UNIX-like machines (e.g./opt/libs:$HOME/testlibs) and with a semicolon on Windows (e.g.D:\libs;%HOMEPATH%\testlibs).

Environment variables can be configured permanently system wide or so thatthey affect only a certain user. Alternatively they can be set temporarilybefore running a command, something that works extremely well in customstart-up scripts.

Using--pythonpath option

Robot Framework has a separate command line option--pythonpath (-P)for adding locations to the module search path.

Multiple locations can be given by separating them with a colon (:) ora semicolon (;) or by using this option multiple times. If the valuecontains both colons and semicolons, it is split from semicolons. Pathscan also beglob patterns matching multiple paths, but they typicallyneed to be escaped when used on the console.

Examples:

--pythonpath libs--pythonpath /opt/testlibs:mylibs.zip:yourlibs--pythonpath /opt/testlibs --pythonpath mylibs.zip --pythonpath yourlibs--pythonpath c:\temp;d:\resources--pythonpath  lib/\*.zip    # '*' is escaped

Note

Both colon and semicolon work regardless the operating system.Using semicolon is new in Robot Framework 5.0.

Configuringsys.path programmatically

Python interpreters store the module search path they use as a list of stringsinsys.pathattribute. This list can be updated dynamically during execution, and changesare taken into account next time when something is imported.

3.5.5   Setting variables

Variables can be set from the command line eitherindividuallyusing the--variable (-v) option or throughvariable fileswith the--variablefile (-V) option. Variables and variablefiles are explained in separate chapters, but the following examplesillustrate how to use these options:

--variable name:value--variable OS:Linux --variable IP:10.0.0.42--variablefile path/to/variables.py--variablefile myvars.py:possible:arguments:here--variable ENVIRONMENT:Windows --variablefile c:\resources\windows.py

3.5.6   Dry run

Robot Framework supports so calleddry run mode where the tests arerun normally otherwise, but the keywords coming from the test librariesare not executed at all. The dry run mode can be used to validate thetest data; if the dry run passes, the data should be syntacticallycorrect. This mode is triggered using option--dryrun.

The dry run execution may fail for following reasons:

  • Using keywords that are not found.
  • Using keywords with wrong number of arguments.
  • Using user keywords that have invalid syntax.

In addition to these failures, normalexecution errors are shown,for example, when test library or resource file imports cannot beresolved.

It is possible to disable dry run validation of specificuser keywordsby adding a specialrobot:no-dry-runkeyword tag to them. This is usefulif a keyword fails in the dry run mode for some reason, but work fine whenexecuted normally.

Note

The dry run mode does not validate variables.

3.5.7   Randomizing execution order

The test execution order can be randomized using option--randomize <what>[:<seed>], where<what> is one of the following:

tests
Test cases inside each test suite are executed in random order.
suites
All test suites are executed in a random order, but test cases insidesuites are run in the order they are defined.
all
Both test cases and test suites are executed in a random order.
none
Neither execution order of test nor suites is randomized.This value can be used to override the earlier value set with--randomize.

It is possible to give a custom seedto initialize the random generator. This is useful if you want to re-run testsusing the same order as earlier. The seed is given as part of the value for--randomize in format<what>:<seed> and it must be an integer.If no seed is given, it is generated randomly. The executed top level testsuite automatically getsmetadata namedRandomized that tells bothwhat was randomized and what seed was used.

Examples:

robot --randomize tests my_test.robotrobot --randomize all:12345 path/to/tests

3.5.8   Programmatic modification of test data

If the provided built-in features to modify test data before executionare not enough, Robot Framework makes it possible to docustom modifications programmatically. This is accomplished by creatinga so calledpre-run modifier and activating it using the--prerunmodifier option.

Pre-run modifiers should be implemented as visitors that can traverse throughthe executable test suite structure and modify it as needed. The visitorinterface is explained as part of theRobot Framework API documentation, and it possible to modify executedtest suites,test cases andkeywords using it. The examples below ought to give an idea ofhow pre-run modifiers can be used and how powerful this functionality is.

When a pre-run modifier is taken into use on the command line using the--prerunmodifier option, it can be specified either as a name ofthe modifier class or a path to the modifier file. If the modifier is givenas a class name, the module containing the class must be in themodule searchpath, and if the module name is different than the class name, the givenname must include both likemodule.ModifierClass. If the modifier is givenas a path, the class name must be same as the file name. For most parts thisworks exactly like whenimporting a test library.

If a modifier requires arguments, like the examples below do, they can bespecified after the modifier name or path using either a colon (:) or asemicolon (;) as a separator. If both are used in the value, the one usedfirst is considered to be the actual separator. Starting from Robot Framework4.0, arguments also support thenamed argument syntax as well asargumentconversion based ontype hints anddefault values the same wayas keywords do.

If more than one pre-run modifier is needed, they can be specified by usingthe--prerunmodifier option multiple times. If similar modifyingis needed before creating logs and reports,programmatic modification ofresults can be enabled using the--prerebotmodifier option.

Pre-run modifiers are executed before other configuration affecting theexecuted test suite and test cases. Most importantly, options related toselecting test cases are processed after modifiers, making it possible touse options like--include also with possible dynamically addedtests.

Tip

Modifiers are taken into use from the command line exactly the sameway aslisteners. See theRegistering listeners from command linesection for more information and examples.

Example: Select every Xth test

The first example shows how a pre-run modifier can remove tests from theexecuted test suite structure. In this example only every Xth tests ispreserved, and the X is given from the command line along with an optionalstart index.

"""Pre-run modifier that selects only every Xth test for execution.Starts from the first test by default. Tests are selected per suite."""fromrobot.apiimportSuiteVisitorclassSelectEveryXthTest(SuiteVisitor):def__init__(self,x:int,start:int=0):self.x=xself.start=startdefstart_suite(self,suite):"""Modify suite's tests to contain only every Xth."""suite.tests=suite.tests[self.start::self.x]defend_suite(self,suite):"""Remove suites that are empty after removing tests."""suite.suites=[sforsinsuite.suitesifs.test_count>0]defvisit_test(self,test):"""Avoid visiting tests and their keywords to save a little time."""pass

If the above pre-run modifier is in a fileSelectEveryXthTest.py andthe file is in themodule search path, it could be used like this:

# Specify the modifier as a path. Run every second test.robot --prerunmodifier path/to/SelectEveryXthTest.py:2 tests.robot# Specify the modifier as a name. Run every third test, starting from the second.robot --prerunmodifier SelectEveryXthTest:3:1 tests.robot

Note

Argument conversion based on type hints likex: int in the aboveexample is new in Robot Framework 4.0 and requires Python 3.

Example: Exclude tests by name

Also the second example removes tests, this time based on a given name pattern.In practice it works like a negative version of the built-in--testoption.

"""Pre-run modifier that excludes tests by their name.Tests to exclude are specified by using a pattern that is both case and spaceinsensitive and supports '*' (match anything) and '?' (match single character)as wildcards."""fromrobot.apiimportSuiteVisitorfromrobot.utilsimportMatcherclassExcludeTests(SuiteVisitor):def__init__(self,pattern):self.matcher=Matcher(pattern)defstart_suite(self,suite):"""Remove tests that match the given pattern."""suite.tests=[tfortinsuite.testsifnotself._is_excluded(t)]def_is_excluded(self,test):returnself.matcher.match(test.name)orself.matcher.match(test.longname)defend_suite(self,suite):"""Remove suites that are empty after removing tests."""suite.suites=[sforsinsuite.suitesifs.test_count>0]defvisit_test(self,test):"""Avoid visiting tests and their keywords to save a little time."""pass

Assuming the above modifier is in a file namedExcludeTests.py, itcould be used like this:

# Exclude test named 'Example'.robot --prerunmodifier path/to/ExcludeTests.py:Example tests.robot# Exclude all tests ending with 'something'.robot --prerunmodifier path/to/ExcludeTests.py:*something tests.robot

Example: Disable setups and teardowns

Sometimes when debugging tests it can be useful to disable setups or teardowns.This can be accomplished by editing the test data, but pre-run modifiers makeit easy to do that temporarily for a single run:

"""Pre-run modifiers for disabling suite and test setups and teardowns."""fromrobot.apiimportSuiteVisitorclassSuiteSetup(SuiteVisitor):defstart_suite(self,suite):suite.setup=NoneclassSuiteTeardown(SuiteVisitor):defstart_suite(self,suite):suite.teardown=NoneclassTestSetup(SuiteVisitor):defstart_test(self,test):test.setup=NoneclassTestTeardown(SuiteVisitor):defstart_test(self,test):test.teardown=None

Assuming that the above modifiers are all in a file nameddisable.pyand this file is in themodule search path, setups and teardowns could bedisabled, for example, as follows:

# Disable suite teardowns.robot --prerunmodifier disable.SuiteTeardown tests.robot# Disable both test setups and teardowns by using '--prerunmodifier' twice.robot --prerunmodifier disable.TestSetup --prerunmodifier disable.TestTeardown tests.robot

Note

Prior to Robot Framework 4.0setup andteardown were accessed viathe intermediatekeywords attribute and, for example, suite setupwas disabled likesuite.keywords.setup = None.

3.5.9   Controlling console output

There are various command line options to control how test execution isreported on the console.

Console output type

The overall console output type is set with the--console option.It supports the following case-insensitive values:

verbose
Every test suite and test case is reported individually. This isthe default.
dotted
Only show. for passed test,F for failed tests,s for skippedtests andx for tests which are skipped becausetest execution exit. Failed tests are listed separatelyafter execution. This output type makes it easy to see are there anyfailures during execution even if there would be a lot of tests.
quiet
No output except forerrors and warnings.
none
No output whatsoever. Useful when creating a custom output using,for example,listeners.

Separate convenience options--dotted (-.) and--quietare shortcuts for--console dotted and--console quiet, respectively.

Examples:

robot --console quiet tests.robotrobot --dotted tests.robot

Console width

The width of the test execution output in the console can be set usingthe option--consolewidth (-W). The default width is 78 characters.

Tip

On many UNIX-like machines you can use handy$COLUMNSenvironment variable like--consolewidth $COLUMNS.

Console colors

The--consolecolors (-C) option is used to control whethercolors should be used in the console output. Colors are implementedusingANSI escape codes with a backup mechanism for older Windowsversions that do not support ANSI codes.

This option supports the following case-insensitive values:

auto
Colors are enabled when outputs are written into the console, but notwhen they are redirected into a file or elsewhere. This is the default.
on
Colors are used also when outputs are redirected. Does not work on Windows.
ansi
Same ason but forces ANSI codes to be used unconditionally on Windows.
off
Colors are disabled.

Note

Using ANSI codes on Windows by default is new in Robot Framework 7.1.

Console links

Result file paths written to the console at the end of the execution are, by default,hyperlinks. This behavior can be controlled with the--consolelinks optionthat accepts the following case-insensitive values:

auto
Paths are converted to links whenconsole colors are enabled. This is the default.
off
Links are unconditionally disabled.

The hyperlink support depends also on the console that is used, but nowadaysthesupport is pretty good. The commonly usedWindows Console does notsupport links, though, but the newerWindows Terminal does.

Note

Hyperlink support is new in Robot Framework 7.1.

Console markers

Special markers. (success) andF (failure) are shown on the console when using theverbose outputand top level keywords in test cases end. The markers allow followingthe test execution in high level, and they are erased when test cases end.

It is possible to configure when markersare used with--consolemarkers (-K) option. It supports the followingcase-insensitive values:

auto
Markers are enabled when the standard output is written into the console,but not when it is redirected into a file or elsewhere. This is the default.
on
Markers are always used.
off
Markers are disabled.

3.5.10   Setting listeners

Listeners can be used to monitor the test execution. When they are taken intouse from the command line, they are specified using the--listenercommand line option. The value can either be a path to a listener ora listener name. See theListener interface section for more detailsabout importing listeners and using them in general.

3.6   Output files

Several output files are created when tests are executed, and all ofthem are somehow related to test results. This section discusses whatoutputs are created, how to configure where they are created, and howto fine-tune their contents.

3.6.1   Different output files

This section explains what different output files can be created andhow to configure where they are created. Output files are configuredusing command line options, which get the path to the output file inquestion as an argument. A special valueNONE(case-insensitive) can be used to disable creating a certain outputfile.

Output directory

All output files can be set using an absolute path, in which case theyare created to the specified place, but in other cases, the path isconsidered relative to the output directory. The default outputdirectory is the directory where the execution is started from, but itcan be altered with the--outputdir (-d) option. The pathset with this option is, again, relative to the execution directory,but can naturally be given also as an absolute path. Regardless of howa path to an individual output file is obtained, its parent directoryis created automatically, if it does not exist already.

Output file

Output files contain all execution results in machine readable XML or JSONformat.Log,report andxUnit files are typically generated based on them,and they can also be combined and otherwise post-processed withRebot.Various external tools also process output files to be able to show detailedexecution information.

Tip

Generatingreport andxUnit files as part of test executiondoes not require processing output files after execution. Disablinglog generation when running tests can thus save memory.

The command line option--output (-o) determines the path wherethe output file is created. The path is relative to theoutput directoryand the default value isoutput.xml when executing tests.Whenpost-processing outputs with Rebot, new output files are not createdunless the--output option is explicitly used.

It is possible to disable the output file by using a special valueNONEwith the--output option. If no outputs are needed, they shouldall be explicitly disabled using--output NONE --report NONE --log NONE.

XML output format

Output files are created using XML by default. The XML output format isdocumented in theresult.xsdschema file.

JSON output format

Robot Framework supports also JSON outputs and this format is used automaticallyif the output file extension is.json. The JSON output format isdocumented in theresult.jsonschema file.

Note

JSON output files are supported during execution starting fromRobot Framework 7.2.Rebot can create them based on XML outputfiles already with Robot Framework 7.0.

Legacy XML format

There were somebackwards incompatible changes to the XML output file format inRobot Framework 7.0. To make it possible to use new Robot Framework versionswith external tools that are not yet updated to support the new format, there isa--legacyoutput option that produces output files that are compatiblewith Robot Framework 6.x and earlier. Robot Framework itself can process outputfiles both in the old and in the new formats.

We hope that external tools are updated soon, but we plan to support thisoption at least until Robot Framework 8.0. If you encounter tools that arenot compatible, please inform the tool developers about changes.

Log file

Log files contain details about the executed test cases in HTMLformat. They have a hierarchical structure showing test suite, testcase and keyword details. Log files are needed nearly every time whentest results are to be investigated in detail. Even though log filesalso have statistics, reports are better forgetting an higher-level overview.

The command line option--log (-l) determines where logfiles are created. Unless the special valueNONE is used,log files are always created and their default name islog.html.

src/ExecutingTestCases/log_passed.png

An example of beginning of a log file

src/ExecutingTestCases/log_failed.png

An example of a log file with keyword details visible

src/ExecutingTestCases/log_skipped.png

An example of a log file with skipped and passed tests

Report file

Report files contain an overview of the test execution results in HTMLformat. They have statistics based on tags and executed test suites,as well as a list of all executed test cases. When both reports andlogs are generated, the report has links to the log file for easynavigation to more detailed information. It is easy to see theoverall test execution status from report, because its backgroundcolor is green, if all tests pass and bright red if any test fails.Background can also be yellow, which means that all tests wereskipped.

The command line option--report (-r) determines wherereport files are created. Similarly as log files, reports are alwayscreated unlessNONE is used as a value, and their defaultname isreport.html.

src/ExecutingTestCases/report_passed.png

An example report file of successful test execution

src/ExecutingTestCases/report_failed.png

An example report file of failed test execution

XUnit compatible result file

XUnit result files contain the test execution summary inxUnit compatibleXML format. These files can thus be used as an input for external tools thatunderstand xUnit reports. For example,Jenkins continuous integration serversupports generating statistics based on xUnit compatibleresults.

Tip

Jenkins also has a separateRobot Framework plugin.

XUnit output files are not created unless the command line option--xunit (-x) is used explicitly. This option requires a path tothe generated xUnit file, relatively to theoutput directory, as a value.

XUnit output files were changed pretty heavily in Robot Framework 5.0.They nowadays contain separate<testsuite> elements for each suite,<testsuite> elements havetimestamp attribute, andsuite documentationandmetadata is stored as<property> elements.

Debug file

Debug files are plain text files that are written during the testexecution. All messages got from test libraries are written to them,as well as information about started and ended test suites, test casesand keywords. Debug files can be used for monitoring the testexecution. This can be done using, for example, a separatefileviewer.pytool, or in UNIX-like systems, simply with thetail-f command.

Debug files are not created unless the command line option--debugfile (-b) is used explicitly.

Timestamping output files

All output files generated by Robot Framework itself can be automatically timestampedwith the option--timestampoutputs (-T). When this option is used,a timestamp in the formatYYYYMMDD-hhmmss is placed betweenthe extension and the base name of each file. The example below would,for example, create output files likeoutput-20080604-163225.xml andmylog-20080604-163225.html:

robot --timestampoutputs --log mylog.html --report NONE tests.robot

Setting titles

The default titles forlogs andreports are generated by prefixingthe name of the top-level test suite withTest Log orTest Report. Custom titles can be given from the command lineusing the options--logtitle and--reporttitle,respectively.

Example:

robot --logtitle "Smoke Test Log" --reporttitle "Smoke Test Report" --include smoke my_tests/

Note

Prior to Robot Framework 3.1, underscores in the given titles wereconverted to spaces. Nowadays spaces need to be escaped or quotedlike in the example above.

Setting background colors

By default thereport file has red background if there are failures,green background if there are passed tests and possibly some skipped ones,and a yellow background if all tests are skipped or no tests have been run.These colors can be customized by using the--reportbackgroundcommand line option, which takes two or three colors separated with a colonas an argument:

--reportbackground blue:red--reportbackground blue:red:orange--reportbackground #00E:#E00

If you specify two colors, the first one will be used instead of thedefault green (pass) color and the second instead of the default red (fail).This allows, for example, using blue instead of green to make backgroundseasier to separate for color blind people.

If you specify three colors, the first two have same semantics as earlierand the last one replaces the default yellow (skip) color.

The specified colors are used as a value for thebodyelement'sbackground CSS property. The value is used as-is andcan be a HTML color name (e.g.red), a hexadecimal value(e.g.#f00 or#ff0000), or an RGB value(e.g.rgb(255,0,0)). The default green, red and yellow colors arespecified using hexadecimal values#9e9,#f66 and#fed84f,respectively.

3.6.2   Log levels

Available log levels

Messages inlog files can have different log levels. Some of themessages are written by Robot Framework itself, but also executedkeywords canlog information using different levels. The availablelog levels are:

FAIL
Used when a keyword fails. Can be used only by Robot Framework itself.
ERROR
Used for displaying errors. Errors are shown inthe console and inthe Test Execution Errors section in log files, but theydo not affect test case statuses. If the--exitonerror option is enabled,errors stop the whole execution, though,
WARN
Used for displaying warnings. Warnings are shown inthe console and inthe Test Execution Errors section in log files, but theydo not affect test case statuses.
INFO
The default level for normal messages. By default,messages below this level are not shown in the log file.
DEBUG
Used for debugging purposes. Useful, for example, forlogging what libraries are doing internally. When a keyword fails,a traceback showing where in the code the failure occurred islogged using this level automatically.
TRACE
More detailed debugging level. The keyword arguments and return valuesare automatically logged using this level.

Setting log level

By default, log messages below theINFO level are not logged, but thisthreshold can be changed from the command line using the--loglevel (-L) option. This option takes any of theavailable log levels as an argument, and that level becomes the newthreshold level. A special valueNONE can also be used todisable logging altogether.

It is possible to use the--loglevel option also whenpost-processing outputs with Rebot. This allows, for example,running tests initially with theTRACE level, and generating smallerlog files for normal viewing later with theINFO level. By defaultall the messages included during execution will be included also withRebot. Messages ignored during the execution cannot be recovered.

Another possibility to change the log level is using theBuiltInkeywordSet Log Level in the test data. It takes the samearguments as the--loglevel option, and it also returns theold level so that it can be restored later, for example, in atestteardown.

Visible log level

If the log file contains messages atDEBUG orTRACE levels, a visible log level drop down is shownin the upper right corner. This allows users to remove messages below chosenlevel from the view. This can be useful especially when running test atTRACE level.

src/ExecutingTestCases/visible_log_level.png

An example log showing the visible log level drop down

By default the drop down will be set at the lowest level in the log file, sothat all messages are shown. The default visible log level can be changed using--loglevel option by giving the default after the normal log levelseparated by a colon:

--loglevel DEBUG:INFO

In the above example, tests are run using levelDEBUG, butthe default visible level in the log file isINFO.

3.6.3   Splitting logs

Normally the log file is just a single HTML file. When the amount of the testcases increases, the size of the file can grow so large that opening it intoa browser is inconvenient or even impossible. Hence, it is possible to usethe--splitlog option to split parts of the log into external filesthat are loaded transparently into the browser when needed.

The main benefit of splitting logs is that individual log parts are so smallthat opening and browsing the log file is possible even if the amountof the test data is very large. A small drawback is that the overall size takenby the log file increases.

Technically the test data related to each test case is saved intoa JavaScript file in the same folder as the main log file. These files havenames such aslog-42.js wherelog is the base name of themain log file and42 is an incremented index.

The JavaScript files are saved to the same directory where thelog fileitself is saved. It is the commonoutput directory by default, butit can be changed with the--log command line option.

Note

When copying the log files, you need to copy also all thelog-*.js files or some information will be missing.

3.6.4   Configuring statistics

There are several command line options that can be used to configureand adjust the contents of theStatistics by Tag,Statisticsby Suite andTest Details by Tag tables in different outputfiles. All these options work both when executing test cases and whenpost-processing outputs.

Configuring displayed suite statistics

When a deeper suite structure is executed, showing all the test suitelevels in theStatistics by Suite table may make the tablesomewhat difficult to read. By default all suites are shown, but you cancontrol this with the command line option--suitestatlevel whichtakes the level of suites to show as an argument:

--suitestatlevel 3

Including and excluding tag statistics

When many tags are used, theStatistics by Tag table can becomequite congested. If this happens, the command line options--tagstatinclude and--tagstatexclude can beused to select which tags to display, similarly as--include and--exclude are used toselect testcases:

--tagstatinclude some-tag --tagstatinclude another-tag--tagstatexclude owner-*--tagstatinclude prefix-* --tagstatexclude prefix-13

Generating combined tag statistics

The command line option--tagstatcombine can be used togenerate aggregate tags that combine statistics from multipletags. The combined tags are specified usingtag patterns where* and? are supported as wildcards andAND,OR andNOT operators can be used for combiningindividual tags or patterns together.

The following examples illustrate creating combined tag statistics usingdifferent patterns, and the figure below shows a snippet of the resultingStatistics by Tag table:

--tagstatcombine owner-*--tagstatcombine smokeANDmytag--tagstatcombine smokeNOTowner-janne*
src/ExecutingTestCases/tagstatcombine.png

Examples of combined tag statistics

As the above example illustrates, the name of the added combined statisticis, by default, just the given pattern. If this is not good enough, itis possible to give a custom name after the pattern by separating themwith a colon (:):

--tagstatcombine "prio1ORprio2:High priority tests"

Note

Prior to Robot Framework 3.1, underscores in the custom name wereconverted to spaces. Nowadays spaces need to be escaped or quotedlike in the example above.

Creating links from tag names

You can add external links to theStatistics by Tag table byusing the command line option--tagstatlink. Arguments to thisoption are given in the formattag:link:name, wheretagspecifies the tags to assign the link to,link is the link tobe created, andname is the name to give to the link.

tag may be a single tag, but more commonly asimple patternwhere* matches anything and? matches any singlecharacter. Whentag is a pattern, the matches to wildcards maybe used inlink andtitle with the syntax%N,where "N" is the index of the match starting from 1.

The following examples illustrate the usage of this option, and thefigure below shows a snippet of the resultingStatistics byTag table when example test data is executed with these options:

--tagstatlink mytag:http://www.google.com:Google--tagstatlink example-bug-*:http://example.com--tagstatlink owner-*:mailto:%1@domain.com?subject=Acceptance_Tests:Send_Mail
src/ExecutingTestCases/tagstatlink.png

Examples of links from tag names

Adding documentation to tags

Tags can be given a documentation with the command line option--tagdoc, which takes an argument in the formattag:doc.tag is the name of the tag to assign thedocumentation to, and it can also be asimple pattern matchingmultiple tags.doc is the assigned documentation.

The given documentation is shown with matching tags in theTestDetails by Tag table, and as a tool tip for these tags in theStatistics by Tag table. If one tag gets multiple documentations,they are combined together and separated with an ampersand.

Examples:

--tagdoc mytag:Example--tagdoc "regression:See http://example.com/info.html"--tagdoc "owner-*:Original author"

Note

Prior to Robot Framework 3.1, underscores in the documentation wereconverted to spaces. Nowadays spaces need to be escaped or quotedlike in the examples above.

3.6.5   Removing and flattening keywords

Most of the content ofoutput files comes from keywords and theirlog messages. When creating higher level reports, log files are not necessarilyneeded at all, and in that case keywords and their messages just take spaceunnecessarily. Log files themselves can also grow overly large, especially ifthey containFOR loops or other constructs that repeat certain keywordsmultiple times.

In these situations, command line options--removekeywords and--flattenkeywords can be used to dispose or flatten unnecessary keywords.They can be used both whenexecuting test cases and whenpost-processingoutputs. When used during execution, they only affect the log file, notthe XML output file. Withrebot they affect both logs and possiblygenerated new output XML files.

Removing keywords

The--removekeywords option removes keywords and their messagesaltogether. It has the following modes of operation, and it can be usedmultiple times to enable multiple modes. Keywords that containerrorsor warnings are not removed except when using theALL mode.

ALL
Remove data from all keywords unconditionally.
PASSED
Remove keyword data from passed test cases. In most cases, log filescreated using this option contain enough information to investigatepossible failures.
FOR
Remove all passed iterations fromFOR loops except the last one.
WHILE
Remove all passed iterations fromWHILE loops except the last one.
WUKS
Remove all failing keywords insideBuiltIn keywordWait Until Keyword Succeeds except the last one.
NAME:<pattern>
Remove data from all keywords matching the given pattern regardless thekeyword status. The pattern is matched against the full name of the keyword,prefixed with the possible library or resource file name likeMyLibrary.Keyword Name. The pattern is case, space, and underscoreinsensitive, and it supportssimple patterns with*,? and[]as wildcards.
TAG:<pattern>
Remove data from keywords with tags that match the given pattern. Tags arecase and space insensitive and they can be specified usingtag patternswhere*,? and[] are supported as wildcards andAND,OR andNOToperators can be used for combining individual tags or patterns together.Can be used both withlibrary keyword tags anduser keyword tags.

Examples:

rebot --removekeywords all --output removed.xml output.xmlrobot --removekeywords passed --removekeywords for tests.robotrobot --removekeywords name:HugeKeyword --removekeywords name:resource.* tests.robotrobot --removekeywords tag:huge tests.robot

Removing keywords is done after parsing theoutput file and generatingan internal model based on it. Thus it does not reduce memory usage as muchasflattening keywords.

Flattening keywords

The--flattenkeywords option flattens matching keywords. In practicethis means that matching keywords get all log messages from their childkeywords, recursively, and child keywords are discarded otherwise. Flatteningsupports the following modes:

FOR
FlattenFOR loops fully.
WHILE
FlattenWHILE loops fully.
ITERATION
Flatten individualFOR andWHILE loop iterations.
FORITEM
Deprecated alias forITERATION.
NAME:<pattern>
Flatten keywords matching the given pattern. Pattern matching rules aresame as whenremoving keywords using theNAME:<pattern> mode.
TAG:<pattern>
Flatten keywords with tags matching the given pattern. Pattern matchingrules are same as whenremoving keywords using theTAG:<pattern> mode.

Examples:

robot --flattenkeywords name:HugeKeyword --flattenkeywords name:resource.* tests.robotrebot --flattenkeywords foritem --output flattened.xml original.xml

Flattening keywords is done already when theoutput file is parsedinitially. This can save a significant amount of memory especially withdeeply nested keyword structures.

Flattening keyword during execution time

Starting from Robot Framework 6.1, it is possible to enable the keyword flattening duringthe execution time. This can be done only on an user keyword level by defining thereserved tagrobot:flatten as akeyword tag. Using this tag will work similarly as the command lineoption described in the previous chapter, e.g. all content except for log messages is removedfrom under the keyword having the tag. One important difference is that in this case, the removedcontent is not written to the output file at all, and thus cannot be accessed at later time.

*** Keywords ***Example    [Tags]robot:flattenLogKeywords and the loop are removed, but logged messages are preserved.FOR     ${i}IN RANGE1101LogIteration${i}/100.END

3.6.6   Automatically expanding keywords

Keywords that have passed are closed in the log file by default. Thus informationthey contain is not visible unless you expand them. If certain keywords haveimportant information that should be visible when the log file is opened, you canuse the--expandkeywords option to set keywords automatically expandedin log file similar to failed keywords. Expanding supports the following modes:

NAME:<pattern>
Expand keywords matching the given pattern. Pattern matching rules aresame as whenremoving keywords using theNAME:<pattern> mode.
TAG:<pattern>
Expand keywords with tags matching the given pattern. Pattern matchingrules are same as whenremoving keywords using theTAG:<pattern> mode.

If you need to expand keywords matching different names or patterns, you canuse the--expandkeywords multiple times.

Examples:

robot --expandkeywords name:SeleniumLibrary.CapturePageScreenshot tests.robotrebot --expandkeywords tag:example --expandkeywords tag:another output.xml

Note

The--expandkeywords option is new in Robot Framework 3.2.

3.6.7   Setting start and end time of execution

Whencombining outputs using Rebot, it is possible to set the startand end time of the combined test suite using the options--starttimeand--endtime, respectively. This is convenient, because by default,combined suites do not have these values. When both the start and end time aregiven, the elapsed time is also calculated based on them. Otherwise the elapsedtime is got by adding the elapsed times of the child test suites together.

It is also possible to use the above mentioned options to set start and endtimes for a single suite when using Rebot. Using these options with asingle output always affects the elapsed time of the suite.

Times must be given as timestamps in the formatYYYY-MM-DDhh:mm:ss.mil, where all separators are optional and the parts frommilliseconds to hours can be omitted. For example,2008-06-1117:59:20.495 is equivalent both to20080611-175920.495 and20080611175920495, and also mere20080611 would work.

Examples:

rebot --starttime 20080611-17:59:20.495 output1.xml output2.xmlrebot --starttime 20080611-175920 --endtime 20080611-180242 *.xmlrebot --starttime 20110302-1317 --endtime 20110302-11418 myoutput.xml

3.6.8   Limiting error message length in reports

If a test case fails and has a long error message, the message shown inreports is automatically cut from the middle to keep reports easier toread. By default messages longer than 40 lines are cut, but that can beconfigured by using the--maxerrorlines command line option.The minimum value for this option is 10, and it is also possible to usea special valueNONE to show the full message.

Full error messages are always visible inlog files as messages ofthe failed keywords.

Note

The--maxerrorlines option is new in Robot Framework 3.1.

3.6.9   Programmatic modification of results

If the provided built-in features to modify results are not enough,Robot Framework makes it possible to do custom modificationsprogrammatically. This is accomplished by creating a model modifier andactivating it using the--prerebotmodifier option.

This functionality works nearly exactly likeprogrammatic modification oftest data that can be enabled with the--prerunmodifier option.The obvious difference is that this time modifiers operate with theresult model, not therunning model. For example, the following modifiermarks all passed tests that have taken more time than allowed as failed:

fromrobot.apiimportSuiteVisitorclassExecutionTimeChecker(SuiteVisitor):def__init__(self,max_seconds:float):self.max_milliseconds=max_seconds*1000defvisit_test(self,test):iftest.status=='PASS'andtest.elapsedtime>self.max_milliseconds:test.status='FAIL'test.message='Test execution took too long.'

If the above modifier would be in fileExecutionTimeChecker.py, itcould be used, for example, like this:

# Specify modifier as a path when running tests. Maximum time is 42 seconds.robot --prerebotmodifier path/to/ExecutionTimeChecker.py:42 tests.robot# Specify modifier as a name when using Rebot. Maximum time is 3.14 seconds.# ExecutionTimeChecker.py must be in the module search path.rebot --prerebotmodifier ExecutionTimeChecker:3.14 output.xml

If more than one model modifier is needed, they can be specified by usingthe--prerebotmodifier option multiple times. When executing tests,it is possible to use--prerunmodifier and--prerebotmodifier options together.

Note

Argument conversion based on type hints likemax_seconds: float inthe above example is new in Robot Framework 4.0 and requires Python 3.

3.6.10   System log

Robot Framework has its own plain-text system log where it writesinformation about

  • Processed and skipped test data files
  • Imported test libraries, resource files and variable files
  • Executed test suites and test cases
  • Created outputs

Normally users never need this information, but it can beuseful when investigating problems with test libraries or Robot Frameworkitself. A system log is not created by default, but it can be enabledby setting the environment variableROBOT_SYSLOG_FILE sothat it contains a path to the selected file.

A system log has the samelog levels as a normal log file, with theexception that instead ofFAIL it has theERRORlevel. The threshold level to use can be altered using theROBOT_SYSLOG_LEVEL environment variable like shown in theexample below. Possibleunexpected errors and warnings arewritten into the system log in addition to the console and the normallog file.

#!/bin/bashexportROBOT_SYSLOG_FILE=/tmp/syslog.txtexportROBOT_SYSLOG_LEVEL=DEBUGrobot--nameSyslog_examplepath/to/tests

4   Extending Robot Framework

4.1   Creating test libraries

Robot Framework's actual testing capabilities are provided by testlibraries. There are many existing libraries, some of which are evenbundled with the core framework, but there is still often a need tocreate new ones. This task is not too complicated because, as thischapter illustrates, Robot Framework's library API is simpleand straightforward.

4.1.1   Introduction

Supported programming languages

Robot Framework itself is written withPython and naturally testlibraries extending it can be implemented using the samelanguage. It is also possible to implement libraries with CusingPython C API, although it is often easier to interact withC code from Python libraries usingctypes module.

Libraries implemented using Python canalso act as wrappers to functionality implemented using otherprogramming languages. A good example of this approach is theRemotelibrary, and another widely used approaches is running externalscripts or tools as separate processes.

Different test library APIs

Robot Framework has three different test library APIs.

Static API

The simplest approach is having a module or a classwith functions/methods which map directly tokeyword names. Keywords also take the samearguments asthe methods implementing them. Keywordsreport failures withexceptions,log by writing to standard output and canreturnvalues using thereturn statement.

Dynamic API

Dynamic libraries are classes that implement a method to get the namesof the keywords they implement, and another method to execute a namedkeyword with given arguments. The names of the keywords to implement, aswell as how they are executed, can be determined dynamically atruntime, but reporting the status, logging and returning values is donesimilarly as in the static API.

Hybrid API

This is a hybrid between the static and the dynamic API. Libraries areclasses with a method telling what keywords they implement, butthose keywords must be available directly. Everything else exceptdiscovering what keywords are implemented is similar as in thestatic API.

All these APIs are described in this chapter. Everything is based onhow the static API works, so its functions are discussed first. Howthedynamic library API and thehybrid library API differ from itis then discussed in sections of their own.

4.1.2   Creating test library class or module

Test libraries can be implemented as Python modules or classes.

Library name

As discussed under theUsing test libraries section, libraries canbeimported by name or path:

*** Settings ***LibraryMyLibraryLibrarymodule.LibraryClassLibrarypath/AnotherLibrary.py

When a library is imported by a name, the library module must be in themodule search path and the name can either refer to a library moduleor to a library class. When a name refers directly to a library class,the name must be in format likemodulename.ClassName. Paths to librariesalways refer to modules.

Even when a library import refers to a module, either by a name or by a path,a class in the module, not the module itself, is used as a library in these cases:

  1. If the module contains a class that has the same name as the module.The class can be either implemented in the module or imported into it.

    This makes it possible to import libraries using simple names likeMyLibraryinstead of specifying both the module and the class likemodule.MyLibrary orMyLibrary.MyLibrary. When importing a library by a path, it is not evenpossible to directly refer to a library class and automatically using a classfrom the imported module is the only option.

  2. If the module contains exactly one class decorated with the@library decorator.In this case the class needs to be implemented in the module, not imported to it.

    This approach has all the same benefits as the earlier one, but it also allowsthe class name to differ from the module name.

    Using the@library decorator for this purpose is new in Robot Framework 7.2.

Tip

If the library name is really long, it is often a good idea to giveit asimpler alias at the import time.

Providing arguments to libraries

All test libraries implemented as classes can take arguments. Thesearguments are specified after the library name when the library is imported,and when Robot Framework creates an instance of the imported library,it passes them to its constructor. Libraries implemented as a modulecannot take any arguments.

The number of arguments needed by the library is the sameas the number of arguments accepted by the library's__init__ method.The default values, argument conversion, and other such features workthe same way as withkeyword arguments. Arguments passedto the library, as well as the library name itself, can be specifiedusing variables, so it is possible to alter them, for example, from thecommand line.

*** Settings ***LibraryMyLibrary10.0.0.18080LibraryAnotherLib    ${ENVIRONMENT}

Example implementations for the libraries used in the above example:

fromexampleimportConnectionclassMyLibrary:def__init__(self,host,port=80):self.connection=Connection(host,port)defsend_message(self,message):self.connection.send(message)
classAnotherLib:def__init__(self,environment):self.environment=environmentdefdo_something(self):ifself.environment=='test':do_something_in_test_environment()else:do_something_in_other_environments()

Library scope

Libraries implemented as classes can have an internal state, which canbe altered by keywords and with arguments to the constructor of thelibrary. Because the state can affect how keywords actually behave, itis important to make sure that changes in one test case do notaccidentally affect other test cases. These kind of dependencies maycreate hard-to-debug problems, for example, when new test cases areadded and they use the library inconsistently.

Robot Framework attempts to keep test cases independent from eachother: by default, it creates new instances of test libraries forevery test case. However, this behavior is not always desirable,because sometimes test cases should be able to share a commonstate. Additionally, all libraries do not have a state and creatingnew instances of them is simply not needed.

Test libraries can control when new libraries are created with aclass attributeROBOT_LIBRARY_SCOPE . This attribute must bea string and it can have the following three values:

TEST

A new instance is created for every test case. A possible suite setupand suite teardown share yet another instance.

Prior to Robot Framework 3.2 this value wasTEST CASE, but nowadaysTEST is recommended. Because all unrecognized values are consideredsame asTEST, both values work with all versions. For the same reasonit is possible to also use valueTASK if the library is targeted forRPA usage more than testing.TEST is also the default value if theROBOT_LIBRARY_SCOPE attribute is not set.

SUITE

A new instance is created for every test suite. The lowest-level testsuites, created from test case files and containing test cases, haveinstances of their own, and higher-level suites all get their own instancesfor their possible setups and teardowns.

Prior to Robot Framework 3.2 this value wasTEST SUITE. That value stillworks, butSUITE is recommended with libraries targeting Robot Framework3.2 and newer.

GLOBAL
Only one instance is created during the whole test execution and itis shared by all test cases and test suites. Libraries created frommodules are always global.

Note

If a library is imported multiple times with differentarguments,a new instance is created every time regardless the scope.

When theSUITE orGLOBAL scopes are used with libraries that have a state,it is recommended that libraries have somespecial keyword for cleaning up the state. This keyword can then beused, for example, in a suite setup or teardown to ensure that testcases in the next test suites can start from a known state. For example,SeleniumLibrary uses theGLOBAL scope to enableusing the same browser in different test cases without having toreopen it, and it also has theClose All Browsers keyword foreasily closing all opened browsers.

Example library using theSUITE scope:

classExampleLibrary:ROBOT_LIBRARY_SCOPE='SUITE'def__init__(self):self._counter=0defcount(self):self._counter+=1print(self._counter)defclear_count(self):self._counter=0

Library version

When a test library is taken into use, Robot Framework tries todetermine its version. This information is then written into thesyslogto provide debugging information. Library documentation toolLibdoc also writes this information into the keyworddocumentations it generates.

Version information is read from attributeROBOT_LIBRARY_VERSION, similarly aslibrary scope isread fromROBOT_LIBRARY_SCOPE. IfROBOT_LIBRARY_VERSION does not exist, information is tried tobe read from__version__ attribute. These attributes must beclass or module attributes, depending whether the library isimplemented as a class or a module.

An example module using__version__:

__version__='0.1'defkeyword():pass

Documentation format

Library documentation toolLibdocsupports documentation in multiple formats. If you want to use somethingelse than Robot Framework's owndocumentation formatting, you can specifythe format in the source code usingROBOT_LIBRARY_DOC_FORMAT attributesimilarly asscope andversion are set with their ownROBOT_LIBRARY_* attributes.

The possible case-insensitive values for documentation format areROBOT (default),HTML,TEXT (plain text),andreST (reStructuredText). Using thereST format requiresthedocutils module to be installed when documentation is generated.

Setting the documentation format is illustrated by the following example thatuses reStructuredText format.SeeDocumenting libraries section andLibdoc chapter for more informationabout documenting test libraries in general.

"""A library for *documentation format* demonstration purposes.This documentation is created using reStructuredText__. Here is a linkto the only \`Keyword\`.__ http://docutils.sourceforge.net"""ROBOT_LIBRARY_DOC_FORMAT='reST'defkeyword():"""**Nothing** to see here. Not even in the table below.    =======  =====  =====    Table    here   has    nothing  to     see.    =======  =====  =====    """pass

Library acting as listener

Listener interface allows external listeners to get notifications abouttest execution. They are called, for example, when suites, tests, and keywordsstart and end. Sometimes getting such notifications is also useful for testlibraries, and they can register a custom listener by usingROBOT_LIBRARY_LISTENER attribute. The value of this attributeshould be an instance of the listener to use, possibly the library itself.

For more information and examples seeLibraries as listeners section.

@library decorator

An easy way to configure libraries implemented as classes is usingtherobot.api.deco.library class decorator. It allows configuring library'sscope,version,custom argument converters,documentation formatandlistener with optional argumentsscope,version,converter,doc_format andlistener, respectively. When these arguments are used, theyset the matchingROBOT_LIBRARY_SCOPE,ROBOT_LIBRARY_VERSION,ROBOT_LIBRARY_CONVERTERS,ROBOT_LIBRARY_DOC_FORMAT andROBOT_LIBRARY_LISTENERattributes automatically:

fromrobot.api.decoimportlibraryfromexampleimportListener@library(scope='GLOBAL',version='3.2b1',doc_format='reST',listener=Listener())classExample:...

The@library decorator also disables theautomatic keyword discoveryby setting theROBOT_AUTO_KEYWORDS argument toFalse by default. Thismeans that it is mandatory to decorate methods with the@keyword decoratorto expose them as keywords. If only that behavior is desired and no furtherconfiguration is needed, the decorator can also be used without parenthesislike:

fromrobot.api.decoimportlibrary@libraryclassExample:...

If needed, the automatic keyword discovery can be enabled by using theauto_keywords argument:

fromrobot.api.decoimportlibrary@library(scope='GLOBAL',auto_keywords=True)classExample:...

The@library decorator only sets class attributesROBOT_LIBRARY_SCOPE,ROBOT_LIBRARY_VERSION,ROBOT_LIBRARY_CONVERTERS,ROBOT_LIBRARY_DOC_FORMATandROBOT_LIBRARY_LISTENER if the respective argumentsscope,version,converters,doc_format andlistener are used. TheROBOT_AUTO_KEYWORDSattribute is set always and its presence can be used as an indication thatthe@library decorator has been used. When attributes are set, theyoverride possible existing class attributes.

When a class is decorated with the@library decorator, it is used as a libraryeven when alibrary import refers only to a module containing it. This is doneregardless does the class name match the module name or not.

Note

The@library decorator is new in Robot Framework 3.2,theconverters argument is new in Robot Framework 5.0, andspecifying that a class in an imported module should be used asa library is new in Robot Framework 7.2.

4.1.3   Creating keywords

What methods are considered keywords

When the static library API is used, Robot Framework uses introspectionto find out what keywords the library class or module implements.By default it excludes methods and functions starting with an underscore.All the methods and functions that are not ignored are considered keywords.For example, the library below implements a single keywordMy Keyword.

classMyLibrary:defmy_keyword(self,arg):returnself._helper_method(arg)def_helper_method(self,arg):returnarg.upper()

Limiting public methods becoming keywords

Automatically considering all public methods and functions keywords typicallyworks well, but there are cases where it is not desired. There are alsosituations where keywords are created when not expected. For example, whenimplementing a library as class, it can be a surprise that also methodsin possible base classes are considered keywords. When implementing a libraryas a module, functions imported into the module namespace becoming keywordsis probably even a bigger surprise.

This section explains how to prevent methods and functions becoming keywords.

Class based libraries

When a library is implemented as a class, it is possible to tellRobot Framework not to automatically expose methods as keywords by settingtheROBOT_AUTO_KEYWORDS attribute to the class with a false value:

classExample:ROBOT_AUTO_KEYWORDS=False

When theROBOT_AUTO_KEYWORDS attribute is set like this, only methods thathave explicitly been decorated with the@keyword decorator or otherwisehave therobot_name attribute become keywords. The@keyword decoratorcan also be used for setting acustom name,tags andargument typesto the keyword.

Although theROBOT_AUTO_KEYWORDS attribute can be set to the classexplicitly, it is more convenient to use the@library decoratorthat sets it toFalse by default:

fromrobot.api.decoimportkeyword,library@libraryclassExample:@keyworddefthis_is_keyword(self):pass@keyword('This is keyword with custom name')defxxx(self):passdefthis_is_not_keyword(self):pass

Note

Both limiting what methods become keywords using theROBOT_AUTO_KEYWORDS attribute and the@library decorator arenew in Robot Framework 3.2.

Another way to explicitly specify what keywords a library implements is usingthedynamic or thehybrid library API.

Module based libraries

When implementing a library as a module, all functions in the module namespacebecome keywords. This is true also with imported functions, and that can causenasty surprises. For example, if the module below would be used as a library,it would contain a keywordExample Keyword, as expected, but alsoa keywordCurrent Thread.

fromthreadingimportcurrent_threaddefexample_keyword():thread_name=current_thread().nameprint(f"Running in thread '{thread_name}'.")

A simple way to avoid imported functions becoming keywords is to onlyimport modules (e.g.import threading) and to use functions via the module(e.gthreading.current_thread()). Alternatively functions could begiven an alias starting with an underscore at the import time (e.g.from threading import current_thread as _current_thread).

A more explicit way to limit what functions become keywords is usingthe module level__all__ attribute thatPython itself uses for similarpurposes. If it is used, only the listed functions can be keywords.For example, the library below implements only one keywordExample Keyword:

fromthreadingimportcurrent_thread__all__=['example_keyword']defexample_keyword():thread_name=current_thread().nameprint(f"Running in thread '{thread_name}'.")defthis_is_not_keyword():pass

If the library is big, maintaining the__all__ attribute when keywords areadded, removed or renamed can be a somewhat big task. Another way to explicitlymark what functions are keywords is using theROBOT_AUTO_KEYWORDS attributesimilarly as it can be used withclass based libraries. When this attributeis set to a false value, only functions explicitly decorated with the@keyword decorator become keywords. For example, also this libraryimplements only one keywordExample Keyword:

fromthreadingimportcurrent_threadfromrobot.api.decoimportkeywordROBOT_AUTO_KEYWORDS=False@keyworddefexample_keyword():thread_name=current_thread().nameprint(f"Running in thread '{thread_name}'.")defthis_is_not_keyword():pass

Note

Limiting what functions become keywords usingROBOT_AUTO_KEYWORDSis a new feature in Robot Framework 3.2.

Using@not_keyword decorator

Functions in modules and methods in classes can be explicitly marked as"not keywords" by using the@not_keyword decorator. When a library isimplemented as a module, this decorator can also be used to avoid importedfunctions becoming keywords.

fromthreadingimportcurrent_threadfromrobot.api.decoimportnot_keywordnot_keyword(current_thread)# Don't expose `current_thread` as a keyword.defexample_keyword():thread_name=current_thread().nameprint(f"Running in thread '{thread_name}'.")@not_keyworddefthis_is_not_keyword():pass

Using the@not_keyword decorator is pretty much the opposite way to avoidfunctions or methods becoming keywords compared to disabling the automatickeyword discovery with the@library decorator or by setting theROBOT_AUTO_KEYWORDS to a false value. Which one to use depends on the context.

Note

The@not_keyword decorator is new in Robot Framework 3.2.

Keyword names

Keyword names used in the test data are compared with method names tofind the method implementing these keywords. Name comparison iscase-insensitive, and also spaces and underscores are ignored. Forexample, the methodhello maps to the keyword nameHello,hello or evenh e l l o. Similarly both thedo_nothing anddoNothing methods can be used as theDo Nothing keyword in the test data.

Example library implemented as a module in theMyLibrary.py file:

defhello(name):print(f"Hello,{name}!")defdo_nothing():pass

The example below illustrates how the example library above can beused. If you want to try this yourself, make sure that the library isin themodule search path.

*** Settings ***LibraryMyLibrary*** Test Cases ***My TestDo NothingHelloworld
Setting custom name

It is possible to expose a different name for a keyword instead of thedefault keyword name which maps to the method name. This can be accomplishedby setting therobot_name attribute on the method to the desired custom name:

deflogin(username,password):...login.robot_name='Login via user panel'
*** Test Cases ***My TestLogin Via User Panel    ${username}    ${password}

Instead of explicitly setting therobot_name attribute like in the aboveexample, it is typically easiest to use the@keyword decorator:

fromrobot.api.decoimportkeyword@keyword('Login via user panel')deflogin(username,password):...

Using this decorator without an argument will have no effect on the exposedkeyword name, but will still set therobot_name attribute. This allowsmarking methods to expose as keywords without actually changing keywordnames. Methods that have therobot_nameattribute also create keywords even if the method name itself would start withan underscore.

Setting a custom keyword name can also enable library keywords to acceptarguments using theembedded arguments syntax.

Keyword tags

Library keywords anduser keywords can have tags. Library keywords candefine them by setting therobot_tags attribute on the method to a listof desired tags. Similarly as whensetting custom name, it is easiest toset this attribute by using the@keyword decorator:

fromrobot.api.decoimportkeyword@keyword(tags=['tag1','tag2'])deflogin(username,password):...@keyword('Custom name',['tags','here'])defanother_example():...

Another option for setting tags is giving them on the last line ofkeyword documentation withTags: prefix and separated by a comma. Forexample:

deflogin(username,password):"""Log user in to SUT.    Tags: tag1, tag2    """...

Keyword arguments

With a static and hybrid API, the information on how many arguments akeyword needs is got directly from the method that implements it.Libraries using thedynamic library API have other means for sharingthis information, so this section is not relevant to them.

The most common and also the simplest situation is when a keyword needs anexact number of arguments. In this case, the methodsimply take exactly those arguments. For example, a method implementing akeyword with no arguments takes no arguments either, a methodimplementing a keyword with one argument also takes one argument, andso on.

Example keywords taking different numbers of arguments:

defno_arguments():print("Keyword got no arguments.")defone_argument(arg):print(f"Keyword got one argument '{arg}'.")defthree_arguments(a1,a2,a3):print(f"Keyword got three arguments '{a1}', '{a2}' and '{a3}'.")

Default values to keywords

It is often useful that some of the arguments that a keyword uses havedefault values.

In Python a method has always exactly one implementation and possibledefault values are specified in the method signature. The syntax,which is familiar to all Python programmers, is illustrated below:

defone_default(arg='default'):print(f"Got argument '{arg}'.")defmultiple_defaults(arg1,arg2='default 1',arg3='default 2'):print(f"Got arguments '{arg1}', '{arg2}' and '{arg3}'.")

The first example keyword above can be used either with zero or onearguments. If no arguments are given,arg gets the valuedefault. If there is one argument,arg gets that value,and calling the keyword with more than one argument fails. In thesecond example, one argument is always required, but the second andthe third one have default values, so it is possible to use the keywordwith one to three arguments.

*** Test Cases ***DefaultsOne DefaultOne DefaultargumentMultiple Defaultsrequired argMultiple Defaultsrequired argoptionalMultiple Defaultsrequired argoptional 1optional 2

Variable number of arguments (*varargs)

Robot Framework supports also keywords that take any number ofarguments.

Python supports methods accepting any number of arguments. The samesyntax works in libraries and, as the examples below show, it can alsobe combined with other ways of specifying arguments:

defany_arguments(*args):print("Got arguments:")forarginargs:print(arg)defone_required(required,*others):print(f"Required:{required}\nOthers:")forarginothers:print(arg)defalso_defaults(req,def1="default 1",def2="default 2",*rest):print(req,def1,def2,rest)
*** Test Cases ***VarargsAny ArgumentsAny ArgumentsargumentAny Argumentsarg 1arg 2arg 3arg 4arg 5One Requiredrequired argOne Requiredrequired arganother argyet anotherAlso DefaultsrequiredAlso Defaultsrequiredthese twohave defaultsAlso Defaults123456

Free keyword arguments (**kwargs)

Robot Framework supportsPython's **kwargs syntax.How to use use keywords that acceptfree keyword arguments,also known asfree named arguments, isdiscussed under the Creating testcases section. In this section we take a look at how to create such keywords.

If you are already familiar how kwargs work with Python, understanding howthey work with Robot Framework test libraries is rather simple. The examplebelow shows the basic functionality:

defexample_keyword(**stuff):forname,valueinstuff.items():print(name,value)
*** Test Cases ***Keyword ArgumentsExample Keywordhello=world# Logs 'hello world'.Example Keywordfoo=1bar=42# Logs 'foo 1' and 'bar 42'.

Basically, all arguments at the end of the keyword call that use thenamed argument syntaxname=value, and that do not match anyother arguments, are passed to the keyword as kwargs. To avoid using a literalvalue likefoo=quux as a free keyword argument, it must beescapedlikefoo\=quux.

The following example illustrates how normal arguments, varargs, and kwargswork together:

defvarious_args(arg=None,*varargs,**kwargs):ifargisnotNone:print('arg:',arg)forvalueinvarargs:print('vararg:',value)forname,valueinsorted(kwargs.items()):print('kwarg:',name,value)
*** Test Cases ***PositionalVarious Argshelloworld# Logs 'arg: hello' and 'vararg: world'.NamedVarious Argsarg=value# Logs 'arg: value'.KwargsVarious Argsa=1b=2c=3# Logs 'kwarg: a 1', 'kwarg: b 2' and 'kwarg: c 3'.Various Argsc=3a=1b=2# Same as above. Order does not matter.Positional and kwargsVarious Args12kw=3# Logs 'arg: 1', 'vararg: 2' and 'kwarg: kw 3'.Named and kwargsVarious Argsarg=valuehello=world# Logs 'arg: value' and 'kwarg: hello world'.Various Argshello=worldarg=value# Same as above. Order does not matter.

For a real world example of using a signature exactly like in the aboveexample, seeRun Process andStart Keyword keywords in theProcess library.

Keyword-only arguments

Starting from Robot Framework 3.1, it is possible to usenamed-only argumentswith different keywords. This supportis provided by Python'skeyword-only arguments. Keyword-only argumentsare specified after possible*varargs or after a dedicated* marker when*varargs are not needed. Possible**kwargs are specified after keyword-onlyarguments.

Example:

defsort_words(*words,case_sensitive=False):key=str.lowerifcase_sensitiveelseNonereturnsorted(words,key=key)defstrip_spaces(word,*,left=True,right=True):ifleft:word=word.lstrip()ifright:word=word.rstrip()returnword
*** Test Cases ***ExampleSort WordsFoobarbaZSort WordsFoobarbaZcase_sensitive=TrueStrip Spaces    ${word}left=False

Positional-only arguments

Python supports so calledpositional-only arguments that make it possible tospecify that an argument can only be given as apositional argument, not asanamed argument likename=value. Positional-only arguments are specifiedbefore normal arguments and a special/ marker must be used after them:

defkeyword(posonly,/,normal):print(f"Got positional-only argument{posonly} and normal argument{normal}.")

The above keyword could be used like this:

*** Test Cases ***Example# Positional-only and normal argument used as positional arguments.Keywordfoobar# Normal argument can also be named.Keywordfoonormal=bar

If a positional-only argument is used with a value that contains an equal signlikeexample=usage, it is not considered to meannamed argument syntaxeven if the part before the= would match the argument name. This ruleonly applies if the positional-only argument is used in its correct positionwithout other arguments using the name argument syntax before it, though.

*** Test Cases ***Example# Positional-only argument gets literal value `posonly=foo` in this case.Keywordposonly=foonormal=bar# This fails.Keywordnormal=barposonly=foo

Positional-only arguments are fully supported starting from Robot Framework 4.0.Using them as positional arguments works also with earlier versions,but using them as named arguments causes an error on Python side.

Argument conversion

Arguments defined in Robot Framework test data are, by default,passed to keywords as Unicode strings. There are, however, several waysto use non-string values as well:

Automatic argument conversion based on function annotations, types specifiedusing the@keyword decorator, and argument default values are all newfeatures in Robot Framework 3.1. TheSupported conversions sectionspecifies which argument conversion are supported in these cases.

Prior to Robot Framework 4.0, automatic conversion was done only if the givenargument was a string. Nowadays it is done regardless the argument type.

Manual argument conversion

If no type information is specified to Robot Framework, all arguments notpassed asvariables are given to keywords as Unicode strings. This includescases like this:

*** Test Cases ***ExampleExample Keyword42False

It is always possible to convert arguments passed as strings insider keywords.In simple cases this means usingint() orfloat() to convert argumentsto numbers, but other kind of conversion is possible as well. When workingwith Boolean values, care must be taken because all non-empty strings,including stringFalse, are considered true by Python. Robot Framework's ownrobot.utils.is_truthy() utility handles this nicely as it considers stringslikeFALSE,NO andNONE (case-insensitively) to be false:

fromrobot.utilsimportis_truthydefexample_keyword(count,case_insensitive):count=int(count)ifis_truthy(case_insensitive):...

Keywords can also use Robot Framework's argument conversion functionality viatherobot.api.TypeInfo class and itsconvert method. This can be usefulif the needed conversion logic is more complicated or the are needs for bettererror reporting than what simply using, for example,int() provides.

fromrobot.apiimportTypeInfodefexample_keyword(count,case_insensitive):count=TypeInfo.from_type(int).convert(count)ifTypeInfo.from_type(bool).convert(case_insensitive):...

Tip

It is generally recommended to specify types using type hints or otherwiseand let Robot Framework handle argument conversion automatically. Manualargument conversion should only be needed in special cases.

Note

robot.api.TypeInfo is new in Robot Framework 7.0.

Specifying argument types using function annotations

Starting from Robot Framework 3.1, arguments passed to keywords are automaticallyconverted if argument type information is available and the type is recognized.The most natural way to specify types is using Pythonfunction annotations.For example, the keyword in the previous example could be implemented asfollows and arguments would be converted automatically:

defexample_keyword(count:int,case_insensitive:bool=True):ifcase_insensitive:...

See theSupported conversions section below for a list of types thatare automatically converted and what values these types accept. It isan error if an argument having one of the supported types is givena value that cannot be converted. Annotating only some of the argumentsis fine.

Annotating arguments with other than the supported types is not an error,and it is also possible to use annotations for other than typingpurposes. In those cases no conversion is done, but annotations arenevertheless shown in the documentation generated byLibdoc.

Keywords can also have a return type annotation specified using the->notation at the end of the signature likedef example() -> int:.This information is not used for anything during execution, but starting fromRobot Framework 7.0 it is shown byLibdoc for documentation purposes.

Specifying argument types using@keyword decorator

An alternative way to specify explicit argument types is using the@keyword decorator. Starting from Robot Framework 3.1,it accepts an optionaltypes argument that can be used to specify argumenttypes either as a dictionary mapping argument names to types or as a listmapping arguments to types based on position. These approaches are shownbelow implementing the same keyword as in earlier examples:

fromrobot.api.decoimportkeyword@keyword(types={'count':int,'case_insensitive':bool})defexample_keyword(count,case_insensitive=True):ifcase_insensitive:...@keyword(types=[int,bool])defexample_keyword(count,case_insensitive=True):ifcase_insensitive:...

Regardless of the approach that is used, it is not necessarily to specifytypes for all arguments. When specifying types as a list, it is possibleto useNone to mark that a certain argument does not have type informationand arguments at the end can be omitted altogether. For example, both of thesekeywords specify the type only for the second argument:

@keyword(types={'second':float})defexample1(first,second,third):...@keyword(types=[None,float])defexample2(first,second,third):...

Starting from Robot Framework 7.0, it is possible to specify the keyword returntype by using key'return' with an appropriate type in the type dictionary.This information is not used for anything during execution, but it is shown byLibdoc for documentation purposes.

If any types are specified using the@keyword decorator, type informationgot fromannotations is ignored with that keyword. Settingtypes toNonelike@keyword(types=None) disables type conversion altogether so that alsotype information got fromdefault values is ignored.

Implicit argument types based on default values

If type information is not got explicitly using annotations or the@keyworddecorator, Robot Framework 3.1 and newer tries to get it based on possibleargument default value. In this examplecount andcase_insensitive gettypesint andbool, respectively:

defexample_keyword(count=-1,case_insensitive=True):ifcase_insensitive:...

When type information is got implicitly based on the default values,argument conversion itself is not as strict as when the information isgot explicitly:

  • Conversion may be attempted also to other "similar" types. For example,if converting to an integer fails, float conversion is attempted.
  • Conversion failures are not errors, keywords get the original value inthese cases instead.

If an argument has an explicit type and a default value, conversion is firstattempted based on the explicit type. If that fails, then conversion is attemptedbased on the default value. In this special case conversion based on the defaultvalue is strict and a conversion failure causes an error.

If argument conversion based on default values is not desired, the wholeargument conversion can be disabled with the@keyword decorator like@keyword(types=None).

Note

Prior to Robot Framework 4.0 conversion was done based on the defaultvalue only if the argument did not have an explict type.

Supported conversions

The table below lists the types that Robot Framework 3.1 and newer convertarguments to. These characteristics apply to all conversions:

  • Type can be explicitly specified usingfunction annotations orthe@keyword decorator.
  • If not explicitly specified, type can be got implicitly fromargumentdefault values.
  • Conversion is done regardless of the type of the given argument. If theargument type is incompatible with the expected type, conversion fails.
  • Conversion failures cause an error if the type has been specified explicitly.If the type is got based on a default value, the given argument is used as-is.

Note

If an argument has both a type hint and a default value, conversion isfirst attempted based on the type hint and then, if that fails, based onthe default value type. This behavior is likely to change in the futureso that conversion based on the default value is doneonly if the argumentdoes not have a type hint. That will change conversion behavior in caseslikearg: list = None whereNone conversion will not be attemptedanymore. Library creators are strongly recommended to specify the defaultvalue type explicitly likearg: list | None = None already now.

The type to use can be specified either using concrete types (e.g.list),by using abstract base classes (ABC) (e.g.Sequence), or by using subclasses of these types (e.g.MutableSequence). Also types in in thetypingmodule that map to the supported concrete types or ABCs (e.g.List) aresupported. In all these cases the argument is converted to the concrete type.

In addition to using the actual types (e.g.int), it is possible to specifythe type using type names as a string (e.g.'int') and some types also havealiases (e.g.'integer'). Matching types to names and aliases iscase-insensitive.

The Accepts column specifies which given argument types are converted.If the given argument already has the expected type, no conversion is done.Other types cause conversion failures.

Supported argument conversions
TypeABCAliasesAcceptsExplanationExamples
bool booleanstr,int,float,None

StringsTRUE,YES,ON and1 are converted toTrue,the empty string as well asFALSE,NO,OFF and0are converted toFalse, and the stringNONE is convertedtoNone. Other strings and other accepted values arepassed as-is, allowing keywords to handle them specially ifneeded. All string comparisons are case-insensitive.

True and false strings can belocalized. See theTranslations appendix for supported translations.

TRUE (converted toTrue)
off (converted toFalse)
example (used as-is)
intIntegralinteger,longstr,float

Conversion is done using theint built-in function. Floatsare accepted only if they can be represented as integersexactly. For example,1.0 is accepted and1.1 is not.If converting a string to an integer fails and the typeis got implicitly based on a default value, conversion tofloat is attempted as well.

Starting from Robot Framework 4.1, it is possible to usehexadecimal, octal and binary numbers by prefixing values with0x,0o and0b, respectively.

Starting from Robot Framework 4.1, spaces and underscores canbe used as visual separators for digit grouping purposes.

Starting from Robot Framework 7.0, strings representing floatsare accepted as long as their decimal part is zero. Thisincludes using the scientific notation like1e100.

42
-1
10 000 000
1e100
0xFF
0o777
0b1010
0xBAD_C0FFEE
${1}
${1.0}
floatRealdoublestr,Real

Conversion is done using thefloat built-in.

Starting from Robot Framework 4.1, spaces and underscores canbe used as visual separators for digit grouping purposes.

3.14
2.9979e8
10 000.000 01
10_000.000_01
Decimal  str,int,float

Conversion is done using theDecimal class.Decimal isrecommended overfloat when decimal numbers need to berepresented exactly.

Starting from Robot Framework 4.1, spaces and underscores canbe used as visual separators for digit grouping purposes.

3.14
10 000.000 01
10_000.000_01
str string,unicodeAny

All arguments are converted to Unicode strings.

New in Robot Framework 4.0.

 
bytes  str,bytearrayStrings are converted to bytes so that each Unicode code pointbelow 256 is directly mapped to a matching byte. Higher codepoints are not allowed.
good
hyvä (converted tohyv\xe4)
\x00 (the null byte)
bytearray  str,bytesSame conversion as withbytes, but the result is abytearray. 
datetime  str,int,float

String timestamps are expected to be inISO 8601 likeformatYYYY-MM-DD hh:mm:ss.mmmmmm, where any non-digitcharacter can be used as a separator or separators can beomitted altogether. Additionally, only the date part ismandatory, all possibly missing time components are consideredto be zeros.

Special valuesNOW andTODAY (case-insensitive) can beused to get the current localdatetime. This is new inRobot Framework 7.3.

Integers and floats are considered to represent seconds sincetheUnix epoch.

2022-02-09T16:39:43.632269
20220209 16:39
2022-02-09
now (current local date and time)
TODAY (same as above)
${1644417583.632269} (Epoch time)
date  str

Same timestamp conversion as withdatetime, butall time components are expected to be omitted or to be zeros.

Special valuesNOW andTODAY (case-insensitive) can beused to get the current localdate. This is new in RobotFramework 7.3.

2018-09-12
20180912
today (current local date)
NOW (same as above)
timedelta  str,int,floatStrings are expected to represent a time interval in one ofthe time formats Robot Framework supports:time as number,time as time string ortime as "timer" string. Integersand floats are considered to be seconds.
42 (42 seconds)
1 minute 2 seconds
01:02 (same as above)
PathPathLike str

Strings are converted topathlib.Path objects.On Windows/ is converted to\ automatically.

New in Robot Framework 6.0.

/tmp/absolute/path
relative/path/to/file.ext
name.txt
Enum  str

The specified type must be an enumeration (a subclass ofEnumorFlag) and given arguments must match its member names.

Matching member names is case, space, underscore and hypheninsensitive, but exact matches have precedence over normalizedmatches. Ignoring hyphens is new in Robot Framework 7.0.

Enumeration documentation and members are shown indocumentation generated byLibdoc automatically.

classDirection(Enum):"""Move direction."""NORTH=auto()NORTH_WEST=auto()defkw(arg:Direction):...
NORTH (Direction.NORTH)
north west (Direction.NORTH_WEST)
IntEnum  str,int

The specified type must be an integer based enumeration (asubclass ofIntEnum orIntFlag) and given arguments mustmatch its member names or values.

Matching member names works the same way as withEnum.Values can be given as integers and as strings that can beconverted to integers.

Enumeration documentation and members are shown indocumentation generated byLibdoc automatically.

New in Robot Framework 4.1.

classPowerState(IntEnum):"""Turn system ON or OFF."""OFF=0ON=1defkw(arg:PowerState):...
OFF (PowerState.OFF)
1 (PowerState.ON)
Literal  Any

Only specified values are accepted. Values can be strings,integers, bytes, Booleans, enums andNone, and used argumentsare converted using the value type specific conversion logic.

Strings are case, space, underscore and hyphen insensitive,but exact matches have precedence over normalized matches.

Literal provides similar functionality asEnum, but doesnot support custom documentation.

New in Robot Framework 7.0.

defkw(arg:Literal['ON','OFF']):...
OFF
on
None  strStringNONE (case-insensitive) is converted to the PythonNone object. Other values cause an error.
None
Any  Any

Any value is accepted. No conversion is done.

New in Robot Framework 6.1.

 
listSequencesequencestr,Sequence

Strings must be Python list literals. They are convertedto actual lists using theast.literal_eval function.They can contain any valuesast.literal_eval supports,including lists and other containers.

If the used type hint islist (e.g.arg: list), sequencesthat are not lists are converted to lists. If the type hint isgenericSequence, sequences are used without conversion.

Aliassequence is new in Robot Framework 7.0.

['one', 'two']
[('one', 1), ('two', 2)]
tuple  str,SequenceSame aslist, but string arguments must be tuple literals.
('one', 'two')
setSet str,ContainerSame aslist, but string arguments must be set literals orset() to create an empty set.
{1, 2, 3, 42}
set()
frozenset  str,ContainerSame asset, but the result is afrozenset.
{1, 2, 3, 42}
frozenset()
dictMappingdictionary,mapping,mapstr,Mapping

Same aslist, but string arguments must be dictionaryliterals.

Aliasmapping is new in Robot Framework 7.0.

{'a': 1, 'b': 2}
{'key': 1, 'nested': {'key': 2}}
TypedDict  str,Mapping

Same asdict, but dictionary items are also convertedto the specified types and items not included in the typespec are not allowed.

New in Robot Framework 6.0. Normaldict conversion wasused earlier.

classConfig(TypedDict):width:intenabled:bool
{'width': 1600, 'enabled': True}

Note

Starting from Robot Framework 5.0, types that have a converted areautomatically shown inLibdoc outputs.

Note

Prior to Robot Framework 4.0, most types supported converting stringNONE (case-insensitively) to PythonNone. That support has been removed andNone conversion is only done if an argument hasNone as anexplicit type or as a default value.

Specifying multiple possible types

Starting from Robot Framework 4.0, it is possible to specify that an argumenthas multiple possible types. In this situation argument conversion is attemptedbased on each type and the whole conversion fails if none of these conversionssucceed.

When using function annotations, the natural syntax to specify that an argumenthas multiple possible types is usingUnion:

fromtypingimportUniondefexample(length:Union[int,float],padding:Union[int,str,None]=None):...

When using Python 3.10 or newer, it is possible to use the nativetype1 | type2syntax instead:

defexample(length:int|float,padding:int|str|None=None):...

Robot Framework 7.0 enhanced the support for the union syntax so that also"stringly typed" unions like'type1 | type2' work. This syntax works alsowith older Python versions:

defexample(length:'int | float',padding:'int | str | None'=None):...

An alternative is specifying types as a tuple. It is not recommended with annotations,because that syntax is not supported by other tools, but it works well withthe@keyword decorator:

fromrobot.api.decoimportkeyword@keyword(types={'length':(int,float),'padding':(int,str,None)})defexample(length,padding=None):...

With the above examples thelength argument would first be converted to aninteger and if that fails then to a float. Thepadding would be firstconverted to an integer, then to a string, and finally toNone.

If the given argument has one of the accepted types, then no conversion is doneand the argument is used as-is. For example, if thelength argument getsvalue1.5 as a float, it would not be converted to an integer. Notice thatusing non-string values like floats as an argument requires using variables asthese examples giving different values to thelength argument demonstrate:

*** Test Cases ***ConversionExample10# Argument is a string. Converted to an integer.Example1.5# Argument is a string. Converted to a float.Example    ${10}# Argument is an integer. Accepted as-is.Example    ${1.5}# Argument is a float. Accepted as-is.

If one of the accepted types is string, then no conversion is done if the givenargument is a string. As the following examples giving different values to thepadding argument demonstrate, also in these cases passing other types ispossible using variables:

*** Test Cases ***ConversionExample1big# Argument is a string. Accepted as-is.Example110# Argument is a string. Accepted as-is.Example1    ${10}# Argument is an integer. Accepted as-is.Example1    ${None}# Argument is `None`. Accepted as-is.Example1    ${1.5}# Argument is a float. Converted to an integer.

If the given argument does not have any of the accepted types, conversion isattempted in the order types are specified. If any conversion succeeds, theresulting value is used without attempting remaining conversions. If no individualconversion succeeds, the whole conversion fails.

If a specified type is not recognized by Robot Framework, then the original argumentvalue is used as-is. For example, with this keyword conversion would first be attemptedto an integer, but if that fails the keyword would get the original argument:

defexample(argument:Union[int,Unrecognized]):...

Starting from Robot Framework 6.1, the above logic works also if an unrecognizedtype is listed before a recognized type likeUnion[Unrecognized, int].Also in this caseint conversion is attempted, and the argument id passed as-isif it fails. With earlier Robot Framework versions,int conversion would not beattempted at all.

Parameterized types

With generics also the parameterized syntax likelist[int] ordict[str, int]works. When this syntax is used, the given value is first converted to the basetype and then individual items are converted to the nested types. Conversionwith different generic types works according to these rules:

  • With lists there can be only one type likelist[float]. All list items areconverted to that type.
  • With tuples there can be any number of types liketuple[int, int] andtuple[str, int, bool]. Tuples used as arguments are expected to haveexactly that amount of items and they are converted to matching types.
  • To create a homogeneous tuple, it is possible to use exactly one type andellipsis liketuple[int, ...]. In this case tuple can have any numberof items and they are all converted to the specified type.
  • With dictionaries there must be exactly two types likedict[str, int].Dictionary keys are converted using the former type and values using the latter.
  • With sets there can be exactly one type likeset[float]. Conversion logicis the same as with lists.

Using the nativelist[int] syntax requiresPython 3.9 or newer. If thereis a need to support also earlier Python versions, it is possible to either usematching types from thetyping module likeList[int] or use the "stringly typed"syntax like'list[int]'.

Note

Support for converting nested types with generics is new inRobot Framework 6.0. Same syntax works also with earlier versions,but arguments are only converted to the base type and nested typesare not used for anything.

Note

Support for "stringly typed" parameterized generics is new inRobot Framework 7.0.

Custom argument converters

In addition to doing argument conversion automatically as explained in theprevious sections, Robot Framework supports custom argument conversion. Thisfunctionality has two main use cases:

  • Overriding the standard argument converters provided by the framework.
  • Adding argument conversion for custom types and for other types not supportedout-of-the-box.

Argument converters are functions or other callables that get arguments usedin data and convert them to desired format before arguments are passed tokeywords. Converters are registered for libraries by settingROBOT_LIBRARY_CONVERTERS attribute (case-sensitive) to a dictionary mappingdesired types to converts. When implementing a library as a module, thisattribute must be set on the module level, and with class based librariesit must be a class attribute. With libraries implemented as classes, it isalso possible to use theconverters argument with the@library decorator.Both of these approaches are illustrated by examples in the following sections.

Note

Custom argument converters are new in Robot Framework 5.0.

Overriding default converters

Let's assume we wanted to create a keyword that acceptsdate objects forusers in Finland where the commonly used date format isdd.mm.yyyy.The usage could look something like this:

*** Test Cases ***ExampleKeyword25.1.2022

Automatic argument conversion supports dates, but it expects themto be inyyyy-mm-dd format so it will not work. A solution is creatinga custom converter and registering it to handledate conversion:

fromdatetimeimportdate# Converter function.defparse_fi_date(value):day,month,year=value.split('.')returndate(int(year),int(month),int(day))# Register converter function for the specified type.ROBOT_LIBRARY_CONVERTERS={date:parse_fi_date}# Keyword using custom converter. Converter is resolved based on argument type.defkeyword(arg:date):print(f'year:{arg.year}, month:{arg.month}, day:{arg.day}')
Conversion errors

If we try using the above keyword with invalid argument likeinvalid, itfails with this error:

ValueError: Argument 'arg' got value 'invalid' that cannot be converted to date: not enough values to unpack (expected 3, got 1)

This error is not too informative and does not tell anything about the expectedformat. Robot Framework cannot provide more information automatically, butthe converter itself can be enhanced to validate the input. If the input isinvalid, the converter should raise aValueError with an appropriate message.In this particular case there would be several ways to validate the input, butusingregular expressions makes it possible to validate both that the inputhas dots (.) in correct places and that date parts contain correct amountof digits:

fromdatetimeimportdateimportredefparse_fi_date(value):# Validate input using regular expression and raise ValueError if not valid.match=re.match(r'(\d{1,2})\.(\d{1,2})\.(\d{4})$',value)ifnotmatch:raiseValueError(f"Expected date in format 'dd.mm.yyyy', got '{value}'.")day,month,year=match.groups()returndate(int(year),int(month),int(day))ROBOT_LIBRARY_CONVERTERS={date:parse_fi_date}defkeyword(arg:date):print(f'year:{arg.year}, month:{arg.month}, day:{arg.day}')

With the above converter code, using the keyword with argumentinvalid failswith a lot more helpful error message:

ValueError: Argument 'arg' got value 'invalid' that cannot be converted to date: Expected date in format 'dd.mm.yyyy', got 'invalid'.
Restricting value types

By default Robot Framework tries to use converters with all given argumentsregardless their type. This means that if the earlier example keyword wouldbe used with a variable containing something else than a string, conversioncode would fail in there.match call. For example, trying to use it withargument${42} would fail like this:

ValueError: Argument 'arg' got value '42' (integer) that cannot be converted to date: TypeError: expected string or bytes-like object

This error situation could naturally handled in the converter code by checkingthe value type, but if the converter only accepts certain types, it is typicallyeasier to just restrict the value to that type. Doing it requires only addingappropriate type hint to the converter:

defparse_fi_date(value:str):...

Notice that this type hintis not used for converting the value before callingthe converter, it is used for strictly restricting which types can be used.With the above addition calling the keyword with${42} would fail like this:

ValueError: Argument 'arg' got value '42' (integer) that cannot be converted to date.

If the converter can accept multiple types, it is possible to specify typesas aUnion. For example, if we wanted to enhance our keyword to accept alsointegers so that they would be considered seconds since theUnix epoch,we could change the converter like this:

fromdatetimeimportdateimportrefromtypingimportUnion# Accept both strings and integers.defparse_fi_date(value:Union[str,int]):# Integers are converted separately.ifisinstance(value,int):returndate.fromtimestamp(value)match=re.match(r'(\d{1,2})\.(\d{1,2})\.(\d{4})$',value)ifnotmatch:raiseValueError(f"Expected date in format 'dd.mm.yyyy', got '{value}'.")day,month,year=match.groups()returndate(int(year),int(month),int(day))ROBOT_LIBRARY_CONVERTERS={date:parse_fi_date}defkeyword(arg:date):print(f'year:{arg.year}, month:{arg.month}, day:{arg.day}')
Converting custom types

A problem with the earlier example is thatdate objects could only be givenindd.mm.yyyy format. It would not work if there was a need tosupport dates in different formats like in this example:

*** Test Cases ***ExampleFinnish25.1.2022US1/25/2022ISO 86012022-01-22

A solution to this problem is creating custom types instead of overridingthe defaultdate conversion:

fromdatetimeimportdateimportrefromtypingimportUnionfromrobot.api.decoimportkeyword,library# Custom type. Extends an existing type but that is not required.classFiDate(date):# Converter function implemented as a classmethod. It could be a normal# function as well, but this way all code is in the same class.@classmethoddeffrom_string(cls,value:str):match=re.match(r'(\d{1,2})\.(\d{1,2})\.(\d{4})$',value)ifnotmatch:raiseValueError(f"Expected date in format 'dd.mm.yyyy', got '{value}'.")day,month,year=match.groups()returncls(int(year),int(month),int(day))# Another custom type.classUsDate(date):@classmethoddeffrom_string(cls,value:str):match=re.match(r'(\d{1,2})/(\d{1,2})/(\d{4})$',value)ifnotmatch:raiseValueError(f"Expected date in format 'mm/dd/yyyy', got '{value}'.")month,day,year=match.groups()returncls(int(year),int(month),int(day))# Register converters using '@library' decorator.@library(converters={FiDate:FiDate.from_string,UsDate:UsDate.from_string})classLibrary:# Uses custom converter supporting 'dd.mm.yyyy' format.@keyworddeffinnish(self,arg:FiDate):print(f'year:{arg.year}, month:{arg.month}, day:{arg.day}')# Uses custom converter supporting 'mm/dd/yyyy' format.@keyworddefus(self,arg:UsDate):print(f'year:{arg.year}, month:{arg.month}, day:{arg.day}')# Uses IS0-8601 compatible default conversion.@keyworddefiso_8601(self,arg:date):print(f'year:{arg.year}, month:{arg.month}, day:{arg.day}')# Accepts date in different formats.@keyworddefany(self,arg:Union[FiDate,UsDate,date]):print(f'year:{arg.year}, month:{arg.month}, day:{arg.day}')
Strict type validation

Converters are not used at all if the argument is of the specified type tobegin with. It is thus easy to enable strict type validation with a customconverter that does not accept any value. For example, theExamplekeyword accepts onlyStrictType instances:

classStrictType:passdefstrict_converter(arg):raiseTypeError(f'Only StrictType instances accepted, got{type(arg).__name__}.')ROBOT_LIBRARY_CONVERTERS={StrictType:strict_converter}defexample(argument:StrictType):assertisinstance(argument,StrictType)

As a convenience, Robot Framework allows setting converter toNone to getthe same effect. For example, this code behaves exactly the same way asthe code above:

classStrictType:passROBOT_LIBRARY_CONVERTERS={StrictType:None}defexample(argument:StrictType):assertisinstance(argument,StrictType)

Note

UsingNone as a strict converter is new in Robot Framework 6.0.An explicit converter function needs to be used with earlier versions.

Accessing the test library from converter

Starting from Robot Framework 6.1, it is possible to access the libraryinstance from a converter function. This allows defining dynamic type conversionsthat depend on the library state. For example, if the library can be configured totest particular locale, you might use the library state to determine how a dateshould be parsed like this:

fromdatetimeimportdateimportredefparse_date(value,library):# Validate input using regular expression and raise ValueError if not valid.# Use locale based from library state to determine parsing format.iflibrary.locale=='en_US':match=re.match(r'(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<year>\d{4})$',value)format='mm/dd/yyyy'else:match=re.match(r'(?P<day>\d{1,2})\.(?P<month>\d{1,2})\.(?P<year>\d{4})$',value)format='dd.mm.yyyy'ifnotmatch:raiseValueError(f"Expected date in format '{format}', got '{value}'.")returndate(int(match.group('year')),int(match.group('month')),int(match.group('day')))ROBOT_LIBRARY_CONVERTERS={date:parse_date}defkeyword(arg:date):print(f'year:{arg.year}, month:{arg.month}, day:{arg.day}')

Thelibrary argument to converter function is optional, i.e. if the converter functiononly accepts one argument, thelibrary argument is omitted. Similar result can be achievedby making the converter function accept only variadic arguments, e.g.def parse_date(*varargs).

Converter documentation

Information about converters is added to outputs produced byLibdocautomatically. This information includes the name of the type, accepted values(if specified using type hints) and documentation. Type information isautomatically linked to all keywords using these types.

Used documentation is got from the converter function by default. If it doesnot have any documentation, documentation is got from the type. Both of theseapproaches to add documentation to converters in the previous example thusproduce the same result:

classFiDate(date):@classmethoddeffrom_string(cls,value:str):"""Date in ``dd.mm.yyyy`` format."""...classUsDate(date):"""Date in ``mm/dd/yyyy`` format."""@classmethoddeffrom_string(cls,value:str):...

Adding documentation is in general recommended to provide users moreinformation about conversion. It is especially important to documentconverter functions registered for existing types, because their owndocumentation is likely not very useful in this context.

@keyword decorator

Although Robot Framework gets lot of information about keywords automatically,such as their names and arguments, there are sometimes needs to configure thisinformation further. This is typically easiest done by using therobot.api.deco.keyword decorator. It has several useful usages that areexplained thoroughly elsewhere and only listened here as a reference:

@not_keyword decorator

Therobot.api.deco.not_keyword decorator can be used fordisabling functions or methods becoming keywords.

Using custom decorators

When implementing keywords, it is sometimes useful to modify them withPython decorators. However, decorators often modify function signaturesand can thus confuse Robot Framework's introspection when determining whicharguments keywords accept. This is especially problematic when creatinglibrary documentation withLibdoc and when using external tools likeRIDE.The easiest way to avoid this problem is decorating thedecorator itself usingfunctools.wraps. Other solutions include usingexternal modules likedecorator andwrapt that allow creating fullysignature-preserving decorators.

Note

Support for "unwrapping" decorators decorated withfunctools.wrapsis a new feature in Robot Framework 3.2.

Embedding arguments into keyword names

Library keywords can also acceptembedded arguments the same way asuser keywords. This section mainly covers the Python syntax to use tocreate such keywords, the embedded arguments syntax itself is covered indetail as part ofuser keyword documentation.

Library keywords with embedded arguments need to have acustom name thatis typically set using the@keyword decorator. Values matching embeddedarguments are passed to the function or method implementing the keyword aspositional arguments. If the function or method accepts more arguments, theycan be passed to the keyword as normal positional or named arguments.Argument names do not need to match the embedded argument names, but thatis generally a good convention.

Keywords accepting embedded arguments:

fromrobot.api.decoimportkeyword@keyword('Select ${animal} from list')defselect_animal_from_list(animal):...@keyword('Number of ${animals} should be')defnumber_of_animals_should_be(animals,count):...

Tests using the above keywords:

*** Test Cases ***Embedded argumentsSelect cat from listSelect dog from listEmbedded and normal argumentsNumber of cats should be2Number of dogs should becount=3

If type information is specified, automaticargument conversion works alsowith embedded arguments:

@keyword('Add ${quantity} copies of ${item} to cart')defadd_copies_to_cart(quantity:int,item:str):...

Note

Embedding type information to keyword names likeAdd ${quantity: int} copies of ${item: str} to cart similarlyas withuser keywordsis not supported with library keywords.

Note

Support for mixing embedded arguments and normal arguments is newin Robot Framework 7.0.

Asynchronous keywords

Starting from Robot Framework 6.1, it is possible to run native asynchronousfunctions (created byasync def) just like normal functions:

importasynciofromrobot.api.decoimportkeyword@keywordasyncdefthis_keyword_waits():awaitasyncio.sleep(5)

You can get the reference of the loop usingasyncio.get_running_loop() orasyncio.get_event_loop(). Be careful when modifying how the loop runs, it isa global resource. For example, never callloop.close() because it will make itimpossible to run any further coroutines. If you have any function or resource thatrequires the event loop, even thoughawait is not used explicitly, you have to defineyour function as async to have the event loop available.

More examples of functionality:

importasynciofromrobot.api.decoimportkeywordasyncdeftask_async():awaitasyncio.sleep(5)@keywordasyncdefexamples():tasks=[task_async()for_inrange(10)]results=awaitasyncio.gather(*tasks)background_task=asyncio.create_task(task_async())awaitbackground_task# If running with Python 3.10 or higherasyncwithasyncio.TaskGroup()astg:task1=tg.create_task(task_async())task2=tg.create_task(task_async())

Note

Robot Framework waits for the function to complete. If you want to have a task that runsfor a long time, use, for example,asyncio.create_task(). It is your responsibility tomanage the task and save a reference to avoid it being garbage collected. If the event loopcloses and a task is still pending, a message will be printed to the console.

Note

If execution of keyword cannot continue for some reason, for example a signal stop,Robot Framework will cancel the async task and any of its children. Other async tasks willcontinue running normally.

4.1.4   Communicating with Robot Framework

After a method implementing a keyword is called, it can use anymechanism to communicate with the system under test. It can then alsosend messages to Robot Framework's log file, return information thatcan be saved to variables and, most importantly, report if thekeyword passed or not.

Reporting keyword status

Reporting keyword status is done simply using exceptions. If an executedmethod raises an exception, the keyword status isFAIL, and if itreturns normally, the status isPASS.

Normal execution failures and errors can be reported using the standard exceptionssuch asAssertionError,ValueError andRuntimeError. There are, however, somespecial cases explained in the subsequent sections where special exceptions are needed.

Error messages

The error message shown in logs, reports and the console is createdfrom the exception type and its message. With generic exceptions (forexample,AssertionError,Exception, andRuntimeError), only the exception message is used, and withothers, the message is created in the formatExceptionType:Actual message.

It is possible to avoid adding theexception type as a prefix to failure message also with non generic exceptions.This is done by adding a specialROBOT_SUPPRESS_NAME attribute withvalueTrue to your exception.

Python:

classMyError(RuntimeError):ROBOT_SUPPRESS_NAME=True

In all cases, it is important for the users that the exception message is asinformative as possible.

HTML in error messages

It is also possible to have HTML formattederror messages by starting the message with text*HTML*:

raiseAssertionError("*HTML* <a href='robotframework.org'>Robot Framework</a> rulez!!")

This method can be used both when raising an exception in a library, likein the example above, andwhen users provide an error message in the test data.

Cutting long messages automatically

If the error message is longer than 40 lines, it will be automaticallycut from the middle to prevent reports from getting too long anddifficult to read. The full error message is always shown in the logmessage of the failed keyword.

Tracebacks

The traceback of the exception is also logged usingDEBUGlog level.These messages are not visible in log files by default because they are veryrarely interesting for normal users. When developing libraries, it is often agood idea to run tests using--loglevel DEBUG.

Exceptions provided by Robot Framework

Robot Framework provides some exceptions that libraries can use for reportingfailures and other events. These exceptions are exposed via therobot.apipackage and contain the following:

Failure
Report failed validation. There is no practical difference in using this exceptioncompared to using the standardAssertionError. The main benefit of using thisexception is that its name is consistent with other provided exceptions.
Error
Report error in execution. Failures related to the system not behaving as expectedshould typically be reported using theFailure exception or the standardAssertionError. This exception can be used, for example, if the keyword is usedincorrectly. There is no practical difference, other than consistent naming withother provided exceptions, compared to using this exception and the standardRuntimeError.
ContinuableFailure
Report failed validation but allow continuing execution.See theContinuable failures section below for more information.
SkipExecution
Mark the executed test or taskskipped.See theSkipping tests section below for more information.
FatalError
Report error that stops the whole execution.See theStopping test execution section below for more information.

Note

All these exceptions are new in Robot Framework 4.0. Other features thanskipping tests, which is also new in Robot Framework 4.0, are availableby other means in earlier versions.

Continuable failures

It is possible tocontinue test execution even when there are failures.The easiest way to do that is using theprovidedrobot.api.ContinuableFailureexception:

fromrobot.apiimportContinuableFailuredefexample_keyword():ifsomething_is_wrong():raiseContinuableFailure('Something is wrong but execution can continue.')...

An alternative is creating a custom exception that has a specialROBOT_CONTINUE_ON_FAILURE attribute set to aTrue value.This is demonstrated by the example below.

classMyContinuableError(RuntimeError):ROBOT_CONTINUE_ON_FAILURE=True

Skipping tests

It is possible toskip tests with a library keyword. The easiest way todo that is using theprovidedrobot.api.SkipExecution exception:

fromrobot.apiimportSkipExecutiondefexample_keyword():iftest_should_be_skipped():raiseSkipExecution('Cannot proceed, skipping test.')...

An alternative is creating a custom exception that has a specialROBOT_SKIP_EXECUTION attribute set to aTrue value.This is demonstrated by the example below.

classMySkippingError(RuntimeError):ROBOT_SKIP_EXECUTION=True

Stopping test execution

It is possible to fail a test case so thatthe whole test execution isstopped. The easiest way to accomplish this is using theprovidedrobot.api.FatalError exception:

fromrobot.apiimportFatalErrordefexample_keyword():ifsystem_is_not_running():raiseFatalError('System is not running!')...

In addition to using therobot.api.FatalError exception, it is possible createa custom exception that has a specialROBOT_EXIT_ON_FAILURE attribute set toaTrue value. This is illustrated by the example below.

classMyFatalError(RuntimeError):ROBOT_EXIT_ON_FAILURE=True

Logging information

Exception messages are not the only way to give information to theusers. In addition to them, methods can also send messages tologfiles simply by writing to the standard output stream (stdout) or tothe standard error stream (stderr), and they can even use differentlog levels. Another, and often better, logging possibility is usingtheprogrammatic logging APIs.

By default, everything written by a method into the standard output iswritten to the log file as a single entry with the log levelINFO. Messages written into the standard error are handledsimilarly otherwise, but they are echoed back to the original stderrafter the keyword execution has finished. It is thus possible to usethe stderr if you need some messages to be visible on the console wheretests are executed.

Using log levels

To use other log levels thanINFO, or to create severalmessages, specify the log level explicitly by embedding the level intothe message in the format*LEVEL* Actual log message.In this formant*LEVEL* must be in the beginning of a line andLEVELmust be one of the available concrete log levelsTRACE,DEBUG,INFO,WARN orERROR, or a pseudo log levelHTML orCONSOLE.The pseudo levels can be used forlogging HTML andlogging to console,respectively.

Errors and warnings

Messages withERROR orWARN level are automatically written to theconsole and a separateTest Execution Errors section in the logfiles. This makes these messages more visible than others and allowsusing them for reporting important but non-critical problems to users.

Logging HTML

Everything normally logged by the library will be converted into aformat that can be safely represented as HTML. For example,<b>foo</b> will be displayed in the log exactly like that andnot asfoo. If libraries want to use formatting, links, displayimages and so on, they can use a special pseudo log levelHTML. Robot Framework will write these messages directly intothe log with theINFO level, so they can use any HTML syntaxthey want. Notice that this feature needs to be used with care,because, for example, one badly placed</table> tag can ruinthe log file quite badly.

When using thepublic logging API, various logging methodshave optionalhtml attribute that can be set toTrueto enable logging in HTML format.

Timestamps

By default messages logged via the standard output or error streamsget their timestamps when the executed keyword ends. This means thatthe timestamps are not accurate and debugging problems especially withlonger running keywords can be problematic.

Keywords have a possibility to add an accurate timestamp to the messagesthey log if there is a need. The timestamp must be given as millisecondssince theUnix epoch and it must be placed after thelog levelseparated from it with a colon:

*INFO:1308435758660* Message with timestamp*HTML:1308435758661* <b>HTML</b> message with timestamp

As illustrated by the examples below, adding the timestamp is easy.It is, however, even easier to get accurate timestamps using theprogrammatic logging APIs. A big benefit of adding timestamps explicitlyis that this approach works also with theremote library interface.

importtimedefexample_keyword():timestamp=int(time.time()*1000)print(f'*INFO:{timestamp}* Message with timestamp')
Logging to console

Libraries have several options for writing messages to the console.As already discussed, warnings and all messages written to thestandard error stream are written both to the log file and to theconsole. Both of these options have a limitation that the messages endup to the console only after the currently executing keyword finishes.

Starting from Robot Framework 6.1, libraries can use a pseudo log levelCONSOLE for logging messagesboth to the log file and to the console:

defmy_keyword(arg):print('*CONSOLE* Message both to log and to console.')

These messages will be logged to the log file using theINFO level similarlyas with theHTML pseudo log level. When using this approach, messagesare logged to the console only after the keyword execution ends.

Another option is writing messages tosys.__stdout__ orsys.__stderr__.When using this approach, messages are written to the console immediatelyand are not written to the log file at all:

importsysdefmy_keyword(arg):print('Message only to console.',file=sys.__stdout__)

The final option is using thepublic logging API. Also in with this approachmessages are written to the console immediately:

fromrobot.apiimportloggerdeflog_to_console(arg):logger.console('Message only to console.')deflog_to_console_and_log_file(arg):logger.info('Message both to log and to console.',also_console=True)
Logging example

In most cases, theINFO level is adequate. The levels below it,DEBUG andTRACE, are useful for writing debug information.These messages are normally not shown, but they can facilitate debuggingpossible problems in the library itself. TheWARN orERROR level canbe used to make messages more visible andHTML is useful if anykind of formatting is needed. LevelCONSOLE can be used when themessage needs to shown both in console and in the log file.

The following examples clarify how logging with different levelsworks.

print('Hello from a library.')print('*WARN* Warning from a library.')print('*ERROR* Something unexpected happen that may indicate a problem in the test.')print('*INFO* Hello again!')print('This will be part of the previous message.')print('*INFO* This is a new message.')print('*INFO* This is <b>normal text</b>.')print('*CONSOLE* This logs into console and log file.')print('*HTML* This is <b>bold</b>.')print('*HTML* <a href="http://robotframework.org">Robot Framework</a>')
16:18:42.123INFOHello from a library.
16:18:42.123WARNWarning from a library.
16:18:42.123ERRORSomething unexpected happen that may indicate a problem in the test.
16:18:42.123INFOHello again!
This will be part of the previous message.
16:18:42.123INFOThis is a new message.
16:18:42.123INFOThis is <b>normal text</b>.
16:18:42.123INFOThis logs into console and log file.
16:18:42.123INFOThis isbold.
16:18:42.123INFORobot Framework

Programmatic logging APIs

Programmatic APIs provide somewhat cleaner way to log information thanusing the standard output and error streams.

Public logging API

Robot Framework has a Python based logging API for writingmessages to the log file and to the console. Test libraries can usethis API likelogger.info('My message') instead of loggingthrough the standard output likeprint('*INFO* My message'). Inaddition to a programmatic interface being a lot cleaner to use, thisAPI has a benefit that the log messages have accuratetimestamps.

The public logging APIis thoroughly documented as part of the APIdocumentation athttps://robot-framework.readthedocs.org. Below isa simple usage example:

fromrobot.apiimportloggerdefmy_keyword(arg):logger.debug(f"Got argument '{arg}'.")do_something()logger.info('<i>This</i> is a boring example',html=True)logger.console('Hello, console!')

An obvious limitation is that test libraries using this logging API havea dependency to Robot Framework. If Robot Framework is not running,the messages are redirected automatically to Python's standardloggingmodule.

Using Python's standardlogging module

In addition to the newpublic logging API, Robot Framework offers abuilt-in support to Python's standardlogging module. Thisworks so that all messages that are received by the root logger of themodule are automatically propagated to Robot Framework's logfile. Also this API produces log messages with accuratetimestamps,but logging HTML messages or writing messages to the console are notsupported. A big benefit, illustrated also by the simple examplebelow, is that using this logging API creates no dependency to RobotFramework.

importloggingdefmy_keyword(arg):logging.debug(f"Got argument '{arg}'.")do_something()logging.info('This is a boring example')

Thelogging module has slightly different log levels thanRobot Framework. Its levelsDEBUG,INFO,WARNING andERROR are mappeddirectly to the matching Robot Framework log levels, andCRITICALis mapped toERROR. Custom log levels are mapped to the closeststandard level smaller than the custom level. For example, a levelbetweenINFO andWARNING is mapped to Robot Framework'sINFO level.

Logging during library initialization

Libraries can also log during the test library import and initialization.These messages do not appear in thelog file like the normal log messages,but are instead written to thesyslog. This allows logging any kind ofuseful debug information about the library initialization. Messages loggedusing theWARN orERROR levels are also visible in thetest execution errorssection in the log file.

Logging during the import and initialization is possible both using thestandard output and error streams and theprogrammatic logging APIs.Both of these are demonstrated below.

Library logging using the logging API during import:

fromrobot.apiimportloggerlogger.debug("Importing library")defkeyword():...

Note

If you log something during initialization, i.e. in Python__init__, the messages may belogged multiple times depending on thelibrary scope.

Returning values

The final way for keywords to communicate back to the core frameworkis returning information retrieved from the system under test orgenerated by some other means. The returned values can beassigned tovariables in the test data and then used as inputs for other keywords,even from different test libraries.

Values are returned using thereturn statement in methods. Normally,one value is assigned into onescalar variable, as illustrated inthe example below. This examplealso illustrates that it is possible to return any objects and to useextended variable syntax to access object attributes.

frommymoduleimportMyObjectdefreturn_string():return"Hello, world!"defreturn_object(name):returnMyObject(name)
*** Test Cases ***Returning one value    ${string} =Return StringShould Be Equal    ${string}Hello, world!    ${object} =Return ObjectRobotShould Be Equal    ${object.name}Robot

Keywords can also return values so that they can be assigned intoseveralscalar variables at once, intoa list variable, orinto scalar variables and a list variable. All these usages requirethat returned values are lists or list-like objects.

defreturn_two_values():return'first value','second value'defreturn_multiple_values():return['a','list','of','strings']
*** Test Cases ***Returning multiple values    ${var1}    ${var2} =Return Two ValuesShould Be Equal    ${var1}first valueShould Be Equal    ${var2}second value    @{list} =Return Two ValuesShould Be Equal    @{list}[0]first valueShould Be Equal    @{list}[1]second value    ${s1}    ${s2}    @{li} =Return Multiple ValuesShould Be Equal    ${s1}${s2}a listShould Be Equal    @{li}[0]@{li}[1]of strings

Detecting is Robot Framework running

Starting from Robot Framework 6.1, it is easy to detect is Robot Frameworkrunning at all and is the dry-run mode active by using therobot_runninganddry_run_active properties of the BuiltIn library. A relatively commonuse case is that library initializers may want to avoid doing some work ifthe library is not used during execution but is initialized, for example,byLibdoc:

fromrobot.libraries.BuiltInimportBuiltInclassMyLibrary:def__init__(self):builtin=BuiltIn()ifbuiltin.robot_runningandnotbuiltin.dry_run_active:# Do some initialization that only makes sense during real execution.

For more information about using the BuiltIn library as a programmatic API,including another example usingrobot_running, see theUsing BuiltIn librarysection.

Communication when using threads

If a library uses threads, it should generally communicate with theframework only from the main thread. If a worker thread has, forexample, a failure to report or something to log, it should pass theinformation first to the main thread, which can then use exceptions orother mechanisms explained in this section for communication with theframework.

This is especially important when threads are run on background whileother keywords are running. Results of communicating with theframework in that case are undefined and can in the worst case cause acrash or a corrupted output file. If a keyword starts something onbackground, there should be another keyword that checks the status ofthe worker thread and reports gathered information accordingly.

Messages logged by non-main threads using the normal logging methods fromprogrammatic logging APIs are silently ignored.

There is also aBackgroundLogger in separaterobotbackgroundlogger project,with a similar API as the standardrobot.api.logger. Normal loggingmethods will ignore messages from other than main thread, but theBackgroundLogger will save the background messages so that they can be laterlogged to Robot's log.

4.1.5   Distributing test libraries

Documenting libraries

A test library without documentation about what keywords itcontains and what those keywords do is rather useless. To easemaintenance, it is highly recommended that library documentation isincluded in the source code and generated from it. Basically, thatmeans usingdocstrings as in the example below.

classMyLibrary:"""This is an example library with some documentation."""defkeyword_with_short_documentation(self,argument):"""This keyword has only a short documentation"""passdefkeyword_with_longer_documentation(self):"""First line of the documentation is here.        Longer documentation continues here and it can contain        multiple lines or paragraphs.        """pass

Python has tools for creating an API documentation of alibrary documented as above. However, outputs from these tools can be slightlytechnical for some users. Another alternative is using RobotFramework's own documentation toolLibdoc. This tool cancreate a library documentation from librariesusing the static library API, such as the ones above, but it also handleslibraries using thedynamic library API andhybrid library API.

The first logical line of a keyword documentation, until the first empty line,is used for a special purpose and should contain a short overall descriptionof the keyword. It is used as ashort documentation byLibdoc (for example,as a tool tip) and also shown in thetest logs.

By default documentation is considered to follow Robot Framework'sdocumentation formatting rules. This simple format allows often usedstyles like*bold* and_italic_, tables, lists, links, etc.It is possible to use also HTML, plaintext andreStructuredText formats. See theDocumentation formatsection for information how to set the format in the library source code andLibdoc chapter for more information about the formats in general.

Note

Prior to Robot Framework 3.1, the short documentation containedonly the first physical line of the keyword documentation.

Testing libraries

Any non-trivial test library needs to be thoroughly tested to preventbugs in them. Of course, this testing should be automated to make iteasy to rerun tests when libraries are changed.

Python has excellent unit testing tools, and they suitevery well for testing libraries. There are no major differences inusing them for this purpose compared to using them for some othertesting. The developers familiar with these tools do not need to learnanything new, and the developers not familiar with them should learnthem anyway.

It is also easy to use Robot Framework itself for testing librariesand that way have actual end-to-end acceptance tests for them. There areplenty of useful keywords in theBuiltIn library for thispurpose. One worth mentioning specifically isRun Keyword And ExpectError, which is useful for testing that keywords report errorscorrectly.

Whether to use a unit- or acceptance-level testing approach depends onthe context. If there is a need to simulate the actual system undertest, it is often easier on the unit level. On the other hand,acceptance tests ensure that keywords do work through RobotFramework. If you cannot decide, of course it is possible to use boththe approaches.

Packaging libraries

After a library is implemented, documented, and tested, it still needsto be distributed to the users. With simple libraries consisting of asingle file, it is often enough to ask the users to copy that filesomewhere and set themodule search path accordingly. Morecomplicated libraries should be packaged to make the installationeasier.

Since libraries are normal programming code, they can be packagedusing normal packaging tools. For information about packaging anddistributing Python code seehttps://packaging.python.org/. When sucha package is installed usingpip or other tools, it is automaticallyin themodule search path.

Deprecating keywords

Sometimes there is a need to replace existing keywords with new onesor remove them altogether. Just informing the users about the changemay not always be enough, and it is more efficient to get warnings atruntime. To support that, Robot Framework has a capability to markkeywordsdeprecated. This makes it easier to find old keywords fromthe test data and remove or replace them.

Keywords can be deprecated by starting their documentation with text*DEPRECATED, case-sensitive, and having a closing* also on the firstline of the documentation. For example,*DEPRECATED*,*DEPRECATED.*, and*DEPRECATED in version 1.5.* are all valid markers.

When a deprecated keyword is executed, a deprecation warning is logged andthe warning is shown also inthe console and the Test Execution Errorssection in log files. The deprecation warning starts with textKeyword'<name>' is deprecated. and has rest of theshort documentation afterthe deprecation marker, if any, afterwards. For example, if the followingkeyword is executed, there will be a warning like shown below in the log file.

defexample_keyword(argument):"""*DEPRECATED!!* Use keyword `Other Keyword` instead.    This keyword does something to given ``argument`` and returns results.    """returndo_something(argument)
20080911 16:00:22.650WARNKeyword 'SomeLibrary.Example Keyword' is deprecated. Use keyword `Other Keyword` instead.

This deprecation system works with most test libraries and also withuser keywords.

4.1.6   Dynamic library API

The dynamic API is in most ways similar to the static API. Forexample, reporting the keyword status, logging, and returning valuesworks exactly the same way. Most importantly, there are no differencesin importing dynamic libraries and using their keywords compared toother libraries. In other words, users do not need to know what APIs theirlibraries use.

Only differences between static and dynamic libraries arehow Robot Framework discovers what keywords a library implements,what arguments and documentation these keywords have, and how thekeywords are actually executed. With the static API, all this isdone using reflection, but dynamic libraries have special methodsthat are used for these purposes.

One of the benefits of the dynamic API is that you have more flexibilityin organizing your library. With the static API, you must have allkeywords in one class or module, whereas with the dynamic API, you can,for example, implement each keyword as a separate class. This use case isnot so important with Python, though, because its dynamic capabilities andmulti-inheritance already give plenty of flexibility, and there is alsopossibility to use thehybrid library API.

Another major use case for the dynamic API is implementing a libraryso that it works as proxy for an actual library possibly running onsome other process or even on another machine. This kind of a proxylibrary can be very thin, and because keyword names and all otherinformation is got dynamically, there is no need to update the proxywhen new keywords are added to the actual library.

This section explains how the dynamic API works between RobotFramework and dynamic libraries. It does not matter for RobotFramework how these libraries are actually implemented (for example,how calls to therun_keyword method are mapped to a correctkeyword implementation), and many different approaches arepossible.Python users may also find thePythonLibCore project useful.

Getting keyword names

Dynamic libraries tell what keywords they implement with theget_keyword_names method. Thismethod cannot take any arguments, and it must return a list or arrayof strings containing the names of the keywords that the library implements.

If the returned keyword names contain several words, they can be returnedseparated with spaces or underscores, or in the camelCase format. Forexample,['first keyword', 'second keyword'],['first_keyword', 'second_keyword'], and['firstKeyword', 'secondKeyword'] would all be mapped to keywordsFirst Keyword andSecond Keyword.

Dynamic libraries must always have this method. If it is missing, orif calling it fails for some reason, the library is considered astatic library.

Marking methods to expose as keywords

If a dynamic library should contain both methods which are meant to be keywordsand methods which are meant to be private helper methods, it may be wise tomark the keyword methods as such so it is easier to implementget_keyword_names.Therobot.api.deco.keyword decorator allows an easy way to do this since itcreates acustom 'robot_name' attribute on the decorated method.This allows generating the list of keywords just by checking for therobot_nameattribute on every method in the library duringget_keyword_names.

fromrobot.api.decoimportkeywordclassDynamicExample:defget_keyword_names(self):# Get all attributes and their values from the library.attributes=[(name,getattr(self,name))fornameindir(self)]# Filter out attributes that do not have 'robot_name' set.keywords=[(name,value)forname,valueinattributesifhasattr(value,'robot_name')]# Return value of 'robot_name', if given, or the original 'name'.return[value.robot_nameornameforname,valueinkeywords]defhelper_method(self):...@keyworddefkeyword_method(self):...

Running keywords

Dynamic libraries have a specialrun_keyword (aliasrunKeyword)method for executing their keywords. When a keyword from a dynamiclibrary is used in the test data, Robot Framework uses therun_keywordmethod to get it executed. This method takes two or three arguments.The first argument is a string containing the name of the keyword to beexecuted in the same format as returned byget_keyword_names. The secondargument is a list ofpositional arguments given to the keyword inthe test data, and the optional third argument is a dictionarycontainingnamed arguments. If the third argument is missing,free namedarguments andnamed-only arguments are not supported, and othernamed arguments are mapped to positional arguments.

Note

Prior to Robot Framework 3.1, normal named arguments weremapped to positional arguments regardless didrun_keywordaccept two or three arguments. The third argument only gotpossible free named arguments.

After getting keyword name and arguments, the library can executethe keyword freely, but it must use the same mechanism tocommunicate with the framework as static libraries. This means usingexceptions for reporting keyword status, logging by writing tothe standard output or by using the provided logging APIs, and usingthe return statement inrun_keyword for returning something.

Every dynamic library must have both theget_keyword_names andrun_keyword methods but rest of the methods in the dynamicAPI are optional. The example below shows a working, albeittrivial, dynamic library.

classDynamicExample:defget_keyword_names(self):return['first keyword','second keyword']defrun_keyword(self,name,args,named_args):print(f"Running keyword '{name}' with positional arguments{args} "f"and named arguments{named_args}.")

Getting keyword arguments

If a dynamic library only implements theget_keyword_names andrun_keyword methods, Robot Framework does not have any informationabout the arguments that the implemented keywords accept. For example,bothFirst Keyword andSecond Keyword in the example abovecould be used with any arguments. This is problematic,because most real keywords expect a certain number of keywords, andunder these circumstances they would need to check the argument countsthemselves.

Dynamic libraries can communicate what arguments their keywords expectby using theget_keyword_arguments (aliasgetKeywordArguments) method.This method gets the name of a keyword as an argument, and it must returna list of strings containing the arguments accepted by that keyword.

Similarly as other keywords, dynamic keywords can require any numberofpositional arguments, havedefault values, acceptvariable number ofarguments, acceptfree named arguments and havenamed-only arguments.The syntax how to represent all these different variables is derived from howthey are specified in Python and explained in the following table.

Representing different arguments withget_keyword_arguments
Argument typeHow to representExamples
No argumentsEmpty list.
[]
One or morepositionalargumentList of strings containingargument names.
['argument']
['arg1', 'arg2', 'arg3']
Default values

Two ways how to representthe argument name and thedefault value:

  • As a string where thename and the default areseparated with=.
  • As a tuple with the nameand the default asseparate items. New inRobot Framework 3.2.

String with= separator:

['name=default']
['a', 'b=1', 'c=2']

Tuple:

[('name', 'default')]
['a', ('b', 1), ('c', 2)]
Positional-onlyargumentsArguments before the/marker. New in RobotFramework 6.1.
['posonly', '/']
['p', 'q', '/', 'normal']
Variable numberof arguments(varargs)Argument after possiblepositional arguments hasa* prefix
['*varargs']
['argument', '*rest']
['a', 'b=42', '*c']
Named-onlyargumentsArguments after varargs ora lone* if there are novarargs. With or withoutdefaults. Requiresrun_keyword tosupportnamed-only arguments.New in Robot Framework 3.1.
['*varargs', 'named']
['*', 'named']
['*', 'x', 'y=default']
['a', '*b', ('c', 42)]
Free namedarguments(kwargs)Last arguments has**prefix. Requiresrun_keyword tosupportfree named arguments.
['**named']
['a', ('b', 42), '**c']
['*varargs', '**kwargs']
['*', 'kwo', '**kws']

When theget_keyword_arguments is used, Robot Framework automaticallycalculates how many positional arguments the keyword requires and does itsupport free named arguments or not. If a keyword is used with invalidarguments, an error occurs andrun_keyword is not even called.

The actual argument names and default values that are returned are alsoimportant. They are needed fornamed argument support and theLibdoctool needs them to be able to create a meaningful library documentation.

As explained in the above table, default values can be specified with argumentnames either as a string like'name=default' or as a tuple like('name', 'default'). The main problem with the former syntax is that alldefault values are considered strings whereas the latter syntax allows usingall objects like('inteter', 1) or('boolean', True). When using otherobjects than strings, Robot Framework can doautomatic argument conversionbased on them.

For consistency reasons, also arguments that do not accept default values canbe specified as one item tuples. For example,['a', 'b=c', '*d'] and[('a',), ('b', 'c'), ('*d',)] are equivalent.

Ifget_keyword_arguments is missing or returns PythonNone for a certainkeyword, that keyword gets an argument specificationaccepting all arguments. This automatic argument spec is either[*varargs, **kwargs] or[*varargs], depending doesrun_keywordsupport free named arguments or not.

Note

Support to specify arguments as tuples like('name', 'default')is new in Robot Framework 3.2. Support for positional-only argumentsin dynamic library API is new in Robot Framework 6.1.

Getting keyword argument types

Robot Framework 3.1 introduced support for automatic argument conversionand the dynamic library API supports that as well. The conversion logicworks exactly like withstatic libraries, but how the type informationis specified is naturally different.

With dynamic libraries types can be returned using the optionalget_keyword_types method (aliasgetKeywordTypes). It can return typesusing a list or a dictionary exactly like types can be specified when usingthe@keyword decorator. Type information can be specified using actualtypes likeint, but especially if a dynamic library gets this informationfrom external systems, using strings like'int' or'integer' may beeasier. See theSupported conversions section for more information aboutsupported types and how to specify them.

Robot Framework does automatic argument conversion also based on theargument default values. Earlier this did not work with the dynamic APIbecause it was possible to specify arguments only as strings. Asdiscussed in the previous section, this was changed in Robot Framework3.2 and nowadays default values returned like('example', True) areautomatically used for this purpose.

Starting from Robot Framework 7.0, dynamic libraries can also specify thekeyword return type by using key'return' with an appropriate type in thereturned type dictionary. This information is not used for anything duringexecution, but it is shown byLibdoc for documentation purposes.

Getting keyword tags

Dynamic libraries can reportkeywordtags by using theget_keyword_tags method (aliasgetKeywordTags). Itgets a keyword name as an argument, and should return corresponding tagsas a list of strings.

Alternatively it is possible to specify tags on the last row of thedocumentation returned by theget_keyword_documentation method discussedbelow. This requires starting the last row withTags: and listing tagsafter it likeTags: first tag, second, third.

Tip

Theget_keyword_tags method is guaranteed to be called beforetheget_keyword_documentation method. This makes it easy toembed tags into the documentation only if theget_keyword_tagsmethod is not called.

Getting keyword documentation

If dynamic libraries want to provide keyword documentation, they can implementtheget_keyword_documentation method (aliasgetKeywordDocumentation). Ittakes a keyword name as an argument and, as the method name implies, returnsits documentation as a string.

The returned documentation is used similarly as the keyworddocumentation string with static libraries.The main use case is getting keywords' documentations into alibrary documentation generated byLibdoc. Additionally,the first line of the documentation (until the first\n) isshown in test logs.

Getting general library documentation

Theget_keyword_documentation method can also be used forspecifying overall library documentation. This documentation is notused when tests are executed, but it can make the documentationgenerated byLibdoc much better.

Dynamic libraries can provide both general library documentation anddocumentation related to taking the library into use. The former isgot by callingget_keyword_documentation with special value__intro__, and the latter is got using value__init__. How the documentation is presented is best testedwithLibdoc in practice.

Dynamic libraries can also specify the general librarydocumentation directly in the code as the docstring of the libraryclass and its__init__ method. If a non-empty documentation isgot both directly from the code and from theget_keyword_documentation method, the latter has precedence.

Getting keyword source information

The dynamic API masks the real implementation of keywords from Robot Frameworkand thus makes it impossible to see where keywords are implemented. Thismeans that editors and other tools utilizing Robot Framework APIs cannotimplement features such as go-to-definition. This problem can be solved byimplementing yet another optional dynamic method namedget_keyword_source(aliasgetKeywordSource) that returns the source information.

The return value from theget_keyword_source method must be a string orNone if no source information is available. In the simplecase it is enough to simply return an absolute path to the file implementingthe keyword. If the line number where the keyword implementation startsis known, it can be embedded to the return value likepath:lineno.Returning only the line number is possible like:lineno.

The source information of the library itself is got automatically fromthe imported library class the same way as with other library APIs. Thelibrary source path is used with all keywords that do not have their ownsource path defined.

Note

Returning source information for keywords is a new feature inRobot Framework 3.2.

Named argument syntax with dynamic libraries

Also the dynamic library API supportsthenamed argument syntax. Using the syntax works based on theargument names and default valuesgot from the library using theget_keyword_arguments method.

If therun_keyword method accepts three arguments, the second argumentgets all positional arguments as a list and the last arguments gets allnamed arguments as a mapping. If it accepts only two arguments, namedarguments are mapped to positional arguments. In the latter case, ifa keyword has multiple arguments with default values and only some ofthe latter ones are given, the framework fills the skipped optionalarguments based on the default values returned by theget_keyword_argumentsmethod.

Using the named argument syntax with dynamic libraries is illustratedby the following examples. All the examples use a keywordDynamicthat has an argument specification[a, b=d1, c=d2]. The comment on each rowshows howrun_keyword would be called in these cases if it has two arguments(i.e. signature isname, args) and if it has three arguments (i.e.name, args, kwargs).

*** Test Cases ***# args          # args, kwargsPositional onlyDynamicx# [x]           # [x], {}Dynamicxy# [x, y]        # [x, y], {}Dynamicxyz# [x, y, z]     # [x, y, z], {}Named onlyDynamica=x# [x]           # [], {a: x}Dynamicc=za=xb=y# [x, y, z]     # [], {a: x, b: y, c: z}Positional and namedDynamicxb=y# [x, y]        # [x], {b: y}Dynamicxyc=z# [x, y, z]     # [x, y], {c: z}Dynamicxb=yc=z# [x, y, z]     # [x], {y: b, c: z}Intermediate missingDynamicxc=z# [x, d1, z]    # [x], {c: z}

Note

Prior to Robot Framework 3.1, all normal named arguments weremapped to positional arguments and the optionalkwargs wasonly used with free named arguments. With the above examplesrun_keyword was always called like it is nowadays called ifit does not supportkwargs.

Free named arguments with dynamic libraries

Dynamic libraries can also supportfree named arguments (**named). A mandatory precondition forthis support is that therun_keyword methodtakes three arguments:the third one will get the free named arguments along with possible othernamed arguments. These arguments are passed to the keyword as a mapping.

What arguments a keyword accepts depends on whatget_keyword_argumentsreturns for it. If the last argument starts with**, that keyword isrecognized to accept free named arguments.

Using the free named argument syntax with dynamic libraries is illustratedby the following examples. All the examples use a keywordDynamicthat has an argument specification[a=d1, b=d2, **named]. The comment showsthe arguments that therun_keyword method is actually called with.

*** Test Cases ***# args, kwargsNo argumentsDynamic# [], {}Only positionalDynamicx# [x], {}Dynamicxy# [x, y], {}Only free namedDynamicx=1# [], {x: 1}Dynamicx=1y=2z=3# [], {x: 1, y: 2, z: 3}Positional and free namedDynamicxy=2# [x], {y: 2}Dynamicxy=2z=3# [x], {y: 2, z: 3}Positional as named and free namedDynamica=1x=1# [], {a: 1, x: 1}Dynamicb=2x=1a=1# [], {a: 1, b: 2, x: 1}

Note

Prior to Robot Framework 3.1, normal named arguments were mappedto positional arguments but nowadays they are part of thekwargs along with the free named arguments.

Named-only arguments with dynamic libraries

Starting from Robot Framework 3.1, dynamic libraries can havenamed-onlyarguments. This requires that therun_keyword methodtakes threearguments: the third getting the named-only arguments along with the othernamed arguments.

In theargument specification returned by theget_keyword_argumentsmethod named-only arguments are specified after possible variable numberof arguments (*varargs) or a lone asterisk (*) if the keyword does notaccept varargs. Named-only arguments can have default values, and the orderof arguments with and without default values does not matter.

Using the named-only argument syntax with dynamic libraries is illustratedby the following examples. All the examples use a keywordDynamicthat has been specified to have argument specification[positional=default, *varargs, named, named2=default, **free]. The commentshows the arguments that therun_keyword method is actually called with.

*** Test Cases ***# args, kwargsOnly named-onlyDynamicnamed=value# [], {named: value}Dynamicnamed=valuenamed2=2# [], {named: value, named2: 2}Named-only with positional and varargsDynamicargumentnamed=xxx# [argument], {named: xxx}Dynamica1a2named=3# [a1, a2], {named: 3}Named-only with positional as namedDynamicnamed=foopositional=bar# [], {positional: bar, named: foo}Named-only with free namedDynamicnamed=valuefoo=bar# [], {named: value, foo=bar}Dynamicnamed2=2third=3named=1# [], {named: 1, named2: 2, third: 3}

Summary

All special methods in the dynamic API are listed in the tablebelow. Method names are listed in the underscore format, but theircamelCase aliases work exactly the same way.

All special methods in the dynamic API
NameArgumentsPurpose
get_keyword_names Return names of the implemented keywords.
run_keywordname, arguments, kwargsExecute the specified keyword with given arguments.kwargs is optional.
get_keyword_argumentsnameReturn keywords'argument specification. Optional method.
get_keyword_typesnameReturn keywords'argument type information. Optional method. New in RF 3.1.
get_keyword_tagsnameReturn keywords'tags. Optional method.
get_keyword_documentationnameReturn keywords' and library'sdocumentation. Optional method.
get_keyword_sourcenameReturn keywords'source. Optional method. New in RF 3.2.

A good example of using the dynamic API is Robot Framework's ownRemote library.

Note

Starting from Robot Framework 7.0, dynamic libraries can have asynchronousimplementations of their special methods.

4.1.7   Hybrid library API

The hybrid library API is, as its name implies, a hybrid between thestatic API and the dynamic API. Just as with the dynamic API, it ispossible to implement a library using the hybrid API only as a class.

Getting keyword names

Keyword names are got in the exactly same way as with the dynamicAPI. In practice, the library needs to have theget_keyword_names orgetKeywordNames method returninga list of keyword names that the library implements.

Running keywords

In the hybrid API, there is norun_keyword method for executingkeywords. Instead, Robot Framework uses reflection to find methodsimplementing keywords, similarly as with the static API. A libraryusing the hybrid API can either have those methods implementeddirectly or, more importantly, it can handle them dynamically.

In Python, it is easy to handle missing methods dynamically with the__getattr__ method. This special method is probably familiarto most Python programmers and they can immediately understand thefollowing example. Others may find it easier to consultPython ReferenceManual first.

fromsomewhereimportexternal_keywordclassHybridExample:defget_keyword_names(self):return['my_keyword','external_keyword']defmy_keyword(self,arg):print(f"My Keyword called with '{args}'.")def__getattr__(self,name):ifname=='external_keyword':returnexternal_keywordraiseAttributeError(f"Non-existing attribute '{name}'.")

Note that__getattr__ does not execute the actual keyword likerun_keyword does with the dynamic API. Instead, it onlyreturns a callable object that is then executed by Robot Framework.

Another point to be noted is that Robot Framework uses the same names thatare returned fromget_keyword_names for finding the methodsimplementing them. Thus the names of the methods that are implemented inthe class itself must be returned in the same format as they aredefined. For example, the library above would not work correctly, ifget_keyword_names returnedMy Keyword instead ofmy_keyword.

Getting keyword arguments and documentation

When this API is used, Robot Framework uses reflection to find themethods implementing keywords, similarly as with the static API. Aftergetting a reference to the method, it searches for arguments anddocumentation from it, in the same way as when using the staticAPI. Thus there is no need for special methods for getting argumentsand documentation like there is with the dynamic API.

Summary

When implementing a test library, the hybrid API has the samedynamic capabilities as the actual dynamic API. A great benefit with it isthat there is no need to have special methods for getting keywordarguments and documentation. It is also often practical that the only realdynamic keywords need to be handled in__getattr__ and otherscan be implemented directly in the main library class.

Because of the clear benefits and equal capabilities, the hybrid APIis in most cases a better alternative than the dynamic API.One notable exception is implementing a library as a proxy foran actual library implementation elsewhere, because then the actualkeyword must be executed elsewhere and the proxy can only pass forwardthe keyword name and arguments.

A good example of using the hybrid API is Robot Framework's ownTelnet library.

4.1.8   Handling Robot Framework's timeouts

Robot Framework has its owntimeouts that can be used for stopping keywordexecution if a test or a keyword takes too much time.There are two things to take into account related to them.

Doing cleanup if timeout occurs

Timeouts are technically implemented usingrobot.errors.TimeoutExceededexception that can occur any time during a keyword execution. If a keywordwants to make sure possible cleanup activities are always done, it needs tohandle these exceptions. Probably the simplest way to handle exceptions isusing Python'stry/finally structure:

defexample():try:do_something()finally:do_cleanup()

A benefit of the above is that cleanup is done regardless of the exception.If there is a need to handle timeouts specially, it is possible to catchTimeoutExceeded explicitly. In that case it is important to re-raise theoriginal exception afterwards:

fromrobot.errorsimportTimeoutExceededdefexample():try:do_something()exceptTimeoutExceeded:do_cleanup()raise

Note

TheTimeoutExceeded exception was namedTimeoutError prior toRobot Framework 7.3. It was renamed to avoid a conflict with Python'sstandard exception with the same name. The old name still exists asa backwards compatible alias in therobot.errors module and canbe used if older Robot Framework versions need to be supported.

Allowing timeouts to stop execution

Robot Framework's timeouts can stop normal Python code, but if the code callsfunctionality implemented using C or some other language, timeouts maynot work. Well behaving keywords should thus avoid long blocking calls thatcannot be interrupted.

As an example,subprocess.run cannot be interrupted on Windows, sothe following simple keyword cannot be stopped by timeouts there:

importsubprocessdefrun_command(command,*args):result=subprocess.run([command,*args],encoding='UTF-8')print(f'stdout:{result.stdout}\nstderr:{result.stderr}')

This problem can be avoided by using the lower levelsubprocess.Popenand handling waiting in a loop with short timeouts. This adds quite a lotof complexity, though, so it may not be worth the effort in all cases.

importsubprocessdefrun_command(command,*args):process=subprocess.Popen([command,*args],encoding='UTF-8',stdout=subprocess.PIPE,stderr=subprocess.PIPE)whileTrue:try:stdout,stderr=process.communicate(timeout=0.1)exceptsubprocess.TimeoutExpired:continueelse:breakprint(f'stdout:{stdout}\nstderr:{stderr}')

4.1.9   Using Robot Framework's internal modules

Test libraries can use Robot Framework'sinternal modules, for example, to get information about the executedtests and the settings that are used. This powerful mechanism tocommunicate with the framework should be used with care, though,because all Robot Framework's APIs are not meant to be used byexternally and they might change radically between different frameworkversions.

Available APIs

API documentation is hosted separatelyat the excellentRead the Docs service. If you are unsure how to usecertain API or is using them forward compatible, please send a questiontomailing list.

Using BuiltIn library

The safest API to use are methods implementing keywords in theBuiltIn library. Changes to keywords are rare and they are alwaysdone so that old usage is first deprecated. One of the most usefulmethods isreplace_variables which allows accessing currentlyavailable variables. The following example demonstrates how to get${OUTPUT_DIR} which is one of the many handyautomaticvariables. It is also possible to set new variables from librariesusingset_test_variable,set_suite_variable andset_global_variable.

importos.pathfromrobot.libraries.BuiltInimportBuiltIndefdo_something(argument):builtin=BuiltIn()output=do_something_that_creates_a_lot_of_output(argument)ifbuiltin.robot_running:output_dir=builtin.replace_variables('${OUTPUT_DIR}')else:output_dir='.'withopen(os.path.join(output_dir,'output.txt'),'w')asfile:file.write(output)print('*HTML* Output written to <a href="output.txt">output.txt</a>')

As the above examples illustrates, BuiltIn also has a convenientrobot_runningproperty fordetecting is Robot Framework running.

The only catch with using methods fromBuiltIn is that allrun_keyword method variants must be handled specially.Methods that userun_keyword methods have to be registeredasrun keywords themselves usingregister_run_keywordmethod inBuiltIn module. This method's documentation explainswhy this needs to be done and obviously also how to do it.

4.1.10   Extending existing test libraries

This section explains different approaches how to add newfunctionality to existing test libraries and how to use them in yourown libraries otherwise.

Modifying original source code

If you have access to the source code of the library you want toextend, you can naturally modify the source code directly. The biggestproblem of this approach is that it can be hard for you to update theoriginal library without affecting your changes. For users it may alsobe confusing to use a library that has different functionality thanthe original one. Repackaging the library may also be a big extratask.

This approach works extremely well if the enhancements are generic andyou plan to submit them back to the original developers. If yourchanges are applied to the original library, they are included in thefuture releases and all the problems discussed above are mitigated. Ifchanges are non-generic, or you for some other reason cannot submitthem back, the approaches explained in the subsequent sectionsprobably work better.

Using inheritance

Another straightforward way to extend an existing library is usinginheritance. This is illustrated by the example below that adds newTitle Should Start With keyword to theSeleniumLibrary.

fromrobot.api.decoimportkeywordfromSeleniumLibraryimportSeleniumLibraryclassExtendedSeleniumLibrary(SeleniumLibrary):@keyworddeftitle_should_start_with(self,expected):title=self.get_title()ifnottitle.startswith(expected):raiseAssertionError(f"Title '{title}' did not start with '{expected}'.")

A big difference with this approach compared to modifying the originallibrary is that the new library has a different name than theoriginal. A benefit is that you can easily tell that you are using acustom library, but a big problem is that you cannot easily use thenew library with the original. First of all your new library will havesame keywords as the original meaning that there is alwaysconflict. Another problem is that the libraries do not share theirstate.

This approach works well when you start to use a new library and wantto add custom enhancements to it from the beginning. Otherwise othermechanisms explained in this section are probably better.

Using other libraries directly

Because test libraries are technically just classes or modules, asimple way to use another library is importing it and using itsmethods. This approach works great when the methods are static and donot depend on the library state. This is illustrated by the earlierexample that usesRobot Framework's BuiltIn library.

If the library has state, however, things may not work as you wouldhope. The library instance you use in your library will not be thesame as the framework uses, and thus changes done by executed keywordsare not visible to your library. The next section explains how to getan access to the same library instance that the framework uses.

Getting active library instance from Robot Framework

BuiltIn keywordGet Library Instance can be used to get thecurrently active library instance from the framework itself. Thelibrary instance returned by this keyword is the same as the frameworkitself uses, and thus there is no problem seeing the correct librarystate. Although this functionality is available as a keyword, it istypically used in test libraries directly by importing theBuiltInlibrary classas discussed earlier. The following example illustrateshow to implement the sameTitle Should Start With keyword as inthe earlier example aboutusing inheritance.

fromrobot.libraries.BuiltInimportBuiltIndeftitle_should_start_with(expected):seleniumlib=BuiltIn().get_library_instance('SeleniumLibrary')title=seleniumlib.get_title()ifnottitle.startswith(expected):raiseAssertionError(f"Title '{title}' did not start with '{expected}'.")

This approach is clearly better than importing the library directlyand using it when the library has a state. The biggest benefit overinheritance is that you can use the original library normally and usethe new library in addition to it when needed. That is demonstrated inthe example below where the code from the previous examples isexpected to be available in a new librarySeLibExtensions.

*** Settings ***LibrarySeleniumLibraryLibrarySeLibExtensions*** Test Cases ***ExampleOpen Browserhttp://example# SeleniumLibraryTitle Should Start WithExample# SeLibExtensions

Libraries using dynamic or hybrid API

Test libraries that use thedynamic orhybrid library API oftenhave their own systems how to extend them. With these libraries youneed to ask guidance from the library developers or consult thelibrary documentation or source code.

4.2   Remote library interface

The remote library interface provides means for having test librarieson different machines than where Robot Framework itself is running,and also for implementing libraries using other languages than thenatively supported Python. For a test library, user remotelibraries look pretty much the same as any other test library, anddeveloping test libraries using the remote library interface is alsovery close to creatingnormal test libraries.

4.2.1   Introduction

There are two main reasons for using the remote library API:

  • It is possible to have actual libraries on different machines thanwhere Robot Framework is running. This allows interestingpossibilities for distributed testing.
  • Test libraries can be implemented using any language that supportsXML-RPC protocol. There exists ready-madegeneric remote serversfor various languages like Python, Java, Ruby, .NET, and so on.

The remote library interface is provided by the Remote library that isone of thestandard libraries.This library does not have any keywords of its own, but it worksas a proxy between the core framework and keywords implementedelsewhere. The Remote library interacts with actual libraryimplementations through remote servers, and the Remote library andservers communicate using a simpleremote protocol on top of anXML-RPC channel. The high level architecture of all this isillustrated in the picture below:

src/ExtendingRobotFramework/remote.png

Robot Framework architecture with Remote library

Note

The remote client uses Python's standardXML-RPC module. It doesnot support custom XML-RPC extensions implemented by some XML-RPCservers.

4.2.2   Putting Remote library to use

Importing Remote library

The Remote library needs to know the address of the remote server butotherwise importing it and using keywords that it provides is nodifferent to how other libraries are used. If you need to use the Remotelibrary multiple times in a suite, or just want to give it a moredescriptive name, you can give it analias when importing it.

*** Settings ***LibraryRemotehttp://127.0.0.1:8270ASExample1LibraryRemotehttp://example.com:8080/ASExample2LibraryRemotehttp://10.0.0.2/example1 minuteASExample3

The URL used by the first example above is also the default addressthat the Remote library uses if no address is given.

The last example above shows how to give a custom timeout to the Remote libraryas an optional second argument. The timeout is used when initially connectingto the server and if a connection accidentally closes. Timeout can begiven in Robot Frameworktime format like60s or2 minutes 10 seconds.The default timeout is typically several minutes, but it depends on theoperating system and its configuration. Notice that setting a timeout thatis shorter than keyword execution time will interrupt the keyword.

Note

Port8270 is the default port that remote servers are expectedto use and it has beenregistered by IANA for this purpose.This port number was selected because 82 and 70 are the ASCII codesof lettersR andF, respectively.

Note

When connecting to the local machine, it is recommended to useIP address127.0.0.1 instead of machine namelocalhost. Thisavoids address resolution that can be extremely slowat least onWindows.

Note

If the URI contains no path after the server address, theXML-RPCmodule used by the Remote library will use/RPC2 path bydefault. In practice usinghttp://127.0.0.1:8270 is thus identicalto usinghttp://127.0.0.1:8270/RPC2. Depending on the remote serverthis may or may not be a problem. No extra path is appended if theaddress has a path even if the path is just/. For example, neitherhttp://127.0.0.1:8270/ norhttp://127.0.0.1:8270/my/path will bemodified.

Starting and stopping remote servers

Before the Remote library can be imported, the remote server providingthe actual keywords must be started. If the server is started beforelaunching the test execution, it is possible to use the normalLibrary setting like in the above example. Alternatively otherkeywords, for example fromProcess orSSH libraries, can startthe server up, but then you may need to useImport Library keywordbecause the library is not available when the test execution starts.

How a remote server can be stopped depends on how it isimplemented. Typically servers support the following methods:

  • Regardless of the library used, remote servers should provideStopRemote Server keyword that can be easily used by executed tests.
  • Remote servers should havestop_remote_server method in theirXML-RPC interface.
  • HittingCtrl-C on the console where the server is running shouldstop the server.
  • The server process can be terminated using tools provided by theoperating system (e.g.kill).

Note

Servers may be configured so that users cannot stop it withStop Remote Server keyword orstop_remote_servermethod.

4.2.3   Supported argument and return value types

Because the XML-RPC protocol does not support all possible objecttypes, the values transferred between the Remote library and remoteservers must be converted to compatible types. This applies to thekeyword arguments the Remote library passes to remote servers and tothe return values servers give back to the Remote library.

Both the Remote library and the Python remote server handle Python valuesaccording to the following rules. Other remote servers should behave similarly.

  • Strings, numbers and Boolean values are passed without modifications.
  • PythonNone is converted to an empty string.
  • All lists, tuples, and other iterable objects (except strings anddictionaries) are passed as lists so that their contents are convertedrecursively.
  • Dictionaries and other mappings are passed as dicts so that their keys areconverted to strings and values converted to supported types recursively.
  • Returned dictionaries are converted to so calleddot-accessible dictsthat allow accessing keys as attributes using theextended variable syntaxlike${result.key}. This works also with nested dictionaries like${root.child.leaf}.
  • Strings containing bytes in the ASCII range that cannot be represented inXML (e.g. the null byte) are sent asBinary objects that internally useXML-RPC base64 data type. Received Binary objects are automatically convertedto byte strings.
  • Other types are converted to strings.

4.2.4   Remote protocol

This section explains the protocol that is used between the Remotelibrary and remote servers. This information is mainly targeted forpeople who want to create new remote servers.

The remote protocol is implemented on top ofXML-RPC, which is asimple remote procedure call protocol using XML over HTTP. Mostmainstream languages (Python, Java, C, Ruby, Perl, Javascript, PHP,...) have a support for XML-RPC either built-in or as an extension.

ThePython remote server can be used as a reference implementation.

Required methods

There are two possibilities how remote servers can provide information aboutthe keywords they contain. They are briefly explained below and documentedmore thoroughly in the subsequent sections.

  1. Remote servers can implement the same methods as thedynamic library APIhas. This meansget_keyword_names method and optionalget_keyword_arguments,get_keyword_types,get_keyword_tags andget_keyword_documentation methods.Notice that using "camel-case names" likegetKeywordNames is notpossible similarly as in the normal dynamic API.
  2. Starting from Robot Framework 4.0, remote servers can have a singleget_library_information method that returns all library and keywordinformation as a single dictionary. If a remote server has this method,the other getter methods likeget_keyword_names are not used at all.This approach has the benefit that there is only one XML-RPC call to getinformation while the approach explained above requires several calls perkeyword. With bigger libraries the difference can be significant.

Regardless how remote servers provide information about their keywords, theymust haverun_keyword method that is used when keywords are executed.How the actual keywords are implemented is not relevant for the Remotelibrary. Remote servers can either act as wrappers for the real testlibraries, like the availablegeneric remote servers do, or they canimplement keywords themselves.

Remote servers should additionally havestop_remote_servermethod in their public interface to ease stopping them. They shouldalso automatically expose this method asStop Remote Serverkeyword to allow using it in the test data regardless of the testlibrary. Allowing users to stop the server is not always desirable,and servers may support disabling this functionality somehow.The method, and also the exposed keyword, should returnTrueorFalse depending on whether stopping is allowed or not. That makes itpossible for external tools to know if stopping the server succeeded.

Usingget_keyword_names and keyword specific getters

This section explains how the Remote library gets keyword names and otherinformation when the server implementsget_keyword_names. The next sectionscovers using the newerget_library_info method.

Theget_keyword_names method must return names of the keyword the servercontains as a list of strings. Remote servers can, and should, also implementget_keyword_arguments,get_keyword_types,get_keyword_tags andget_keyword_documentation methods to provide more information aboutthe keywords. All these methods take the name of the keyword as an argumentand what they must return is explained in the table below.

Keyword specific getter methods
MethodReturn value
get_keyword_argumentsArguments as a list of strings in thesame format as with dynamic libraries.
get_keyword_typesType information as a list or dictionary of strings. See below for details.
get_keyword_documentationDocumentation as a string.
get_keyword_tagsTags as a list of strings.

Type information used forargument conversion can be returned either asa list mapping type names to arguments based on position or as a dictionarymapping argument names to type names directly. In practice this works the sameway as whenspecifying types using the @keyword decorator with normallibraries. The difference is that because the XML-RPC protocol does not supportarbitrary values, type information needs to be specified using type namesor aliases like'int' or'integer', not using actual types likeint.AdditionallyNone ornull values may not be allowed by the XML-RPC server,but an empty string can be used to indicate that certain argument does nothave type information instead.

Argument conversion is supported also based on default values using thesame logic as with normal libraries. For this to work, arguments withdefault values must be returned as tuples, not as strings, thesame wayas with dynamic libraries. For example, argument conversion works ifargument information is returned like[('count', 1), ('caseless', True)]but not if it is['count=1', 'caseless=True'].

Remote servers can also providegeneral library documentation tobe used when generating documentation with theLibdoc tool. This informationis got by callingget_keyword_documentation with special values__intro__and__init__.

Note

get_keyword_types is new in Robot Framework 3.1 and support forargument conversion based on defaults is new in Robot Framework 4.0.

Usingget_library_information

Theget_library_information method allows returning information about the wholelibrary in one XML-RPC call. The information must be returned as a dictionary wherekeys are keyword names and values are nested dictionaries containing keyword information.The dictionary can also contain separate entries for generic library information.

The keyword information dictionary can contain keyword arguments, documentation,tags and types, and the respective keys areargs,doc,tags andtypes.Information must be provided using same semantics as whenget_keyword_arguments,get_keyword_documentation,get_keyword_tags andget_keyword_types discussedin the previous section. If some information is not available, it can be omittedfrom the info dictionary altogether.

get_library_information supports also returning general library documentationto be used withLibdoc. It is done by including special__intro__ and__init__entries into the returned library information dictionary.

For example, a Python library like

"""Library documentation."""fromrobot.api.decoimportkeyword@keyword(tags=['x','y'])defexample(a:int,b=True):"""Keyword documentation."""passdefanother():pass

could be mapped into this kind of library information dictionary:

{    '__intro__': {'doc': 'Library documentation'}    'example': {'args': ['a', 'b=True'],                'types': ['int'],                'doc': 'Keyword documentation.',                'tags': ['x', 'y']}    'another: {'args': []}}

Note

get_library_information is new in Robot Framework 4.0.

Executing remote keywords

When the Remote library wants the server to execute some keyword, itcalls the remote server'srun_keyword method and passes it thekeyword name, a list of arguments, and possibly a dictionary offree named arguments. Base types can be used asarguments directly, but more complex types areconverted to supportedtypes.

The server must return results of the execution in a result dictionary(or map, depending on terminology) containing items explained in thefollowing table. Notice that only thestatus entry is mandatory,others can be omitted if they are not applicable.

Entries in the remote result dictionary
NameExplanation
statusMandatory execution status. Either PASS or FAIL.
outputPossible output to write into the log file. Must be givenas a single string but can contain multiple messages anddifferentlog levels in format*INFO* Firstmessage\n*HTML* <b>2nd</b>\n*WARN* Another message. Itis also possible to embedtimestamps to the log messageslike*INFO:1308435758660* Message with timestamp.
returnPossible return value. Must be one of thesupportedtypes.
errorPossible error message. Used only when the execution fails.
tracebackPossible stack trace towrite into the log file usingDEBUG level when the execution fails.
continuableWhen set toTrue, or any value consideredTrue inPython, the occurred failure is consideredcontinuable.
fatalLikecontinuable, but denotes that the occurredfailure isfatal.

Different argument syntaxes

The Remote library is adynamic library, and in general it handlesdifferent argument syntaxesaccording to the same rules as any otherdynamic library.This includes mandatory arguments, default values, varargs, as wellasnamed argument syntax.

Also free named arguments (**kwargs) works mostly thesame wayas with other dynamic libraries. First of all, theget_keyword_arguments must return an argument specification thatcontains**kwargs exactly like with any other dynamic library.The main difference is thatremote servers'run_keyword method must have anoptional third argumentthat gets the kwargs specified by the user. The third argument must be optionalbecause, for backwards-compatibility reasons, the Remote library passes kwargsto therun_keyword method only when they have been used in the test data.

In practicerun_keyword should look something like the followingPython and Java examples, depending on how the language handles optionalarguments.

defrun_keyword(name,args,kwargs=None):# ...
publicMaprun_keyword(Stringname,Listargs){// ...}publicMaprun_keyword(Stringname,Listargs,Mapkwargs){// ...}

4.3   Listener interface

Robot Framework's listener interface provides a powerful mechanism for gettingnotifications and for inspecting and modifying data and results during execution.Listeners are called, for example, when suites, tests and keywords start and end,when output files are ready, and finally when the whole execution ends.Example usages include communicating with external test management systems,sending a message when a test fails, and modifying tests during execution.

Listeners are implemented as classes or modules with certain special methods.They can betaken into use from the command line and beregisteredby libraries. The former listeners are active during the whole executionwhile the latter are active only when executing suites where libraries registeringthem are imported.

There are two supported listener interface versions,listener version 2 andlistener version 3. They have mostly the same methods, but these methods arecalled with different arguments. The newer listener version 3 is more powerfuland generally recommended.

4.3.1   Listener structure

Listeners are implement as modules or classessimilarly as libraries.They can implement certain named hook methods depending on what events theyare interested in. For example, if a listener wants to get a notification whena test starts, it can implement thestart_test method. As discussed in thesubsequent sections, different listener versions have slightly different set ofavailable methods and they also are called with different arguments.

# Listener implemented as a module using the listener API version 3.defstart_suite(data,result):print(f"Suite '{data.name}' starting.")defend_test(data,result):print(f"Test '{result.name}' ended with status{result.status}.")

Listeners do not need to implement any explicit interface, it is enough tosimply implement needed methods and they will be recognized automatically.There are, however, base classesrobot.api.interfaces.ListenerV2androbot.api.interfaces.ListenerV3 that can be used to getmethod name completion in editors, type hints, and so on.

# Same as the above example, but uses an optional base class and type hints.fromrobotimportresult,runningfromrobot.api.interfacesimportListenerV3classExample(ListenerV3):defstart_suite(self,data:running.TestSuite,result:result.TestSuite):print(f"Suite '{data.name}' starting.")defend_test(self,data:running.TestCase,result:result.TestCase):print(f"Test '{result.name}' ended with status{result.status}.")

Note

Optional listener base classes are new in Robot Framework 6.1.

In addition to using "snake case" likestart_test with listener method names,it is possible to use "camel case" likestartTest. This support was addedwhen it was possible to run Robot Framework on Jython and implement listenersusing Java. It is preserved for backwards compatibility reasons, but notrecommended with new listeners.

4.3.2   Listener interface versions

There are two supported listener interface versions with version numbers 2 and 3.A listener can specify which version to use by having aROBOT_LISTENER_API_VERSIONattribute with value 2 or 3, respectively. Starting from Robot Framework 7.0,the listener version 3 is used by default if the version is not specified.

Listener version 2 andlistener version 3 have mostly the same methods,but arguments passed to these methods are different. Arguments given to listener 2methods are strings and dictionaries containing information about execution. Thisinformation can be inspected and sent further, but it is not possible tomodify it directly. Listener 3 methods get the same model objects that Robot Frameworkitself uses, and these model objects can be both inspected and modified.

Listener version 3 is more powerful than the older listener version 2and generally recommended.

Listener version 2

Listeners using the listener API version 2 get notifications about various eventsduring execution, but they do not have access to actually executed tests and thuscannot directly affect the execution or created results.

Listener methods in the API version 2 are listed in the following tableand in the API docs of the optionalListenerV2 base class.All methods related to test execution progress have the same signaturemethod(name, attributes), whereattributes is a dictionary containingdetails of the event. Listener methods are free to do whatever they wantto do with the information they receive, but they cannot directly changeit. If that is needed,listener version 3 can be used instead.

Methods in the listener API 2
MethodArgumentsDocumentation
start_suitename, attributes

Called when a test suite starts.

Contents of the attribute dictionary:

  • id: Suite id.s1 for the top level suite,s1-s1for its first child suite,s1-s2 for the secondchild, and so on.
  • longname: Suite name including parent suites.
  • doc: Suite documentation.
  • metadata:Free suite metadata as a dictionary.
  • source: An absolute path of the file/directory the suitewas created from.
  • suites: Names of the direct child suites this suite hasas a list.
  • tests: Names of the tests this suite has as a list.Does not include tests of the possible child suites.
  • totaltests: The total number of tests in this suite.and all its sub-suites as an integer.
  • starttime: Suite execution start time.
end_suitename, attributes

Called when a test suite ends.

Contents of the attribute dictionary:

  • id: Same as instart_suite.
  • longname: Same as instart_suite.
  • doc: Same as instart_suite.
  • metadata: Same as instart_suite.
  • source: Same as instart_suite.
  • starttime: Same as instart_suite.
  • endtime: Suite execution end time.
  • elapsedtime: Total execution time in milliseconds asan integer
  • status: Suite status as stringPASS,FAIL orSKIP.
  • statistics: Suite statistics (number of passedand failed tests in the suite) as a string.
  • message: Error message if suite setup or teardownhas failed, empty otherwise.
start_testname, attributes

Called when a test case starts.

Contents of the attribute dictionary:

  • id: Test id in format likes1-s2-t2, wherethe beginning is the parent suite id and the last partshows test index in that suite.
  • longname: Test name including parent suites.
  • originalname: Test name with possible variablesunresolved. New in RF 3.2.
  • doc: Test documentation.
  • tags: Test tags as a list of strings.
  • template: The name of the template used for the test.An empty string if the test not templated.
  • source: An absolute path of the test case source file.New in RF 4.0.
  • lineno: Line number where the test starts in the sourcefile. New in RF 3.2.
  • starttime: Test execution execution start time.
end_testname, attributes

Called when a test case ends.

Contents of the attribute dictionary:

  • id: Same as instart_test.
  • longname: Same as instart_test.
  • originalname: Same as instart_test.
  • doc: Same as instart_test.
  • tags: Same as instart_test.
  • template: Same as instart_test.
  • source: Same as instart_test.
  • lineno: Same as instart_test.
  • starttime: Same as instart_test.
  • endtime: Test execution execution end time.
  • elapsedtime: Total execution time in milliseconds asan integer
  • status: Test status as stringPASS,FAIL orSKIP.
  • message: Status message. Normally an errormessage or an empty string.
start_keywordname, attributes

Called when a keyword or a control structure such asIF/ELSEorTRY/EXCEPT starts.

With keywordsname is the full keyword name containingpossible library or resource name as a prefix likeMyLibrary.Example Keyword. With control structuresnamecontains string representation of parameters.

Keywords and control structures share most of attributes, butcontrol structures can have additional attributes dependingon theirtype.

Shared attributes:

  • type: String specifying type of the started item. Possiblevalues are:KEYWORD,SETUP,TEARDOWN,FOR,WHILE,ITERATION,IF,ELSE IF,ELSE,TRY,EXCEPT,FINALLY,VAR,RETURN,BREAK,CONTINUE andERROR.All type values were changed in RF 4.0 and in RF 5.0FOR ITERATION was changed toITERATION.
  • kwname: Name of the keyword without library orresource prefix. String representation of parameters withcontrol structures.
  • libname: Name of the library or resource file the keywordbelongs to. An empty string with user keywords in a testcase file and with control structures.
  • doc: Keyword documentation.
  • args: Keyword's arguments as a list of strings.
  • assign: A list of variable names that keyword'sreturn value is assigned to.
  • tags:Keyword tags as a list of strings.
  • source: An absolute path of the file where the keyword wasused. New in RF 4.0.
  • lineno: Line where the keyword was used. Typically aninteger, but can beNone if a keyword has been executed bya listener. New in RF 4.0.
  • status: Initial keyword status.NOT RUN if keyword isnot executed (e.g. due to an earlier failure),NOT SETotherwise. New in RF 4.0.
  • starttime: Keyword execution start time.

Additional attributes forFOR types:

  • variables: Assigned variables for each loop iterationas a list or strings.
  • flavor: Type of loop (e.g.IN RANGE).
  • values: List of values being looped overas a list or strings.
  • start: Start configuration. Only used withIN ENUMERATEloops. New in RF 6.1.
  • mode: Mode configuration. Only used withIN ZIP loops.New in RF 6.1.
  • fill: Fill value configuration. Only used withIN ZIPloops. New in RF 6.1.

Additional attributes forITERATION types withFOR loops:

  • variables: Variables and string representations of theircontents for oneFOR loop iteration as a dictionary.

Additional attributes forWHILE types:

  • condition: The looping condition.
  • limit: The maximum iteration limit.
  • on_limit: What to do if the limit is exceeded.Valid values arepass andfail. New in RF 7.0.
  • on_limit_message: The custom error raised when thelimit of the WHILE loop is reached. New in RF 6.1.

Additional attributes forIF andELSE IF types:

  • condition: The conditional expression being evaluated.WithELSE IF new in RF 6.1.

Additional attributes forEXCEPT types:

  • patterns: The exception patterns being matchedas a list or strings.
  • pattern_type: The type of pattern match (e.g.GLOB).
  • variable: The variable containing the captured exception.

Additional attributes forRETURN types:

  • values: Return values from a keyword as a list or strings.

Additional attributes forVAR types:

  • name: Variable name.
  • value: Variable value. A string with scalar variables anda list otherwise.
  • scope: Variable scope (e.g.GLOBAL) as a string.

Additional attributes for control structures are in generalnew in RF 6.0.VAR is new in RF 7.0.

end_keywordname, attributes

Called when a keyword or a control structure ends.

name is the full keyword name containingpossible library or resource name as a prefix.For example,MyLibrary.Example Keyword.

Control structures have additional attributes, which changebased on thetype attribute. For descriptions of allpossible attributes, see thestart_keyword section.

Contents of the attribute dictionary:

  • type: Same as withstart_keyword.
  • kwname: Same as withstart_keyword.
  • libname: Same as withstart_keyword.
  • doc: Same as withstart_keyword.
  • args: Same as withstart_keyword.
  • assign: Same as withstart_keyword.
  • tags: Same as withstart_keyword.
  • source: Same as withstart_keyword.
  • lineno: Same as withstart_keyword.
  • starttime: Same as withstart_keyword.
  • endtime: Keyword execution end time.
  • elapsedtime: Total execution time in milliseconds asan integer
  • status: Keyword status as stringPASS,FAIL,SKIPorNOT RUN.SKIP andNOT RUN are new in RF 4.0.
log_messagemessage

Called when an executed keyword writes a log message.

message is a dictionary with the following contents:

  • message: The content of the message.
  • level:Log level used in logging the message.
  • timestamp: Message creation time in formatYYYY-MM-DD hh:mm:ss.mil.
  • html: Stringyes orno denoting whether the messageshould be interpreted as HTML or not.

Not called if the message level is below the currentthreshold level.

messagemessage

Called when the framework itself writes asyslog message.

message is a dictionary with the same contents as withlog_message method.

library_importname, attributes

Called when a library has been imported.

name is the name of the imported library. If the libraryhas been given a custom name when imported it usingAS,name is the specified alias.

Contents of the attribute dictionary:

  • args: Arguments passed to the library as a list.
  • originalname: The original library name if the library hasbeen given an alias usingAS, otherwise same asname.
  • source: An absolute path to the library source. An emptystring if getting thesource of the library failed for some reason.
  • importer: An absolute path to the file importing thelibrary.None whenBuiltIn is imported as well as whenusing theImport Library keyword.
resource_importname, attributes

Called when a resource file has been imported.

name is the name of the imported resource file withoutthe file extension.

Contents of the attribute dictionary:

  • source: An absolute path to the imported resource file.
  • importer: An absolute path to the file importing theresource file.None when using theImport Resourcekeyword.
variables_importname, attributes

Called when a variable file has been imported.

name is the name of the imported variable file withthe file extension.

Contents of the attribute dictionary:

  • args: Arguments passed to the variable file as a list.
  • source: An absolute path to the imported variable file.
  • importer: An absolute path to the file importing theresource file.None when using theImportVariables keyword.
output_filepath

Called when writing to anoutput file is ready.

path is an absolute path to the file as a string ora stringNone if creating the output file is disabled.

log_filepath

Called when writing to alog file is ready.

path is an absolute path to the file as a string.Not called if creating the log file is disabled.

report_filepath

Called when writing to areport file is ready.

path is an absolute path to the file as a string.Not called if creating the report file is disabled.

xunit_filepath

Called when writing to anxunit file is ready.

path is an absolute path to the file as a string.Only called if creating the xunit file is enabled.

debug_filepath

Called when writing to adebug file is ready.

path is an absolute path to the file as a string.Only called if creating the debug file is enabled.

close 

Called when the whole test execution ends.

Withlibrary listeners called when the library goes outof scope.

Listener version 3

Listener version 3 has mostly the same methods aslistener version 2,but arguments of the methods related to test execution are different.These methods get actual running and result model objects that used by RobotFramework itself, and listeners can both query information they need andchange the model objects on the fly.

Listener version 3 was enhanced heavily in Robot Framework 7.0 when it gotmethods related to keywords and control structures. It was enhanced furtherin Robot Framework 7.1 when it got methods related to library, resource fileand variable file imports.

Listener version 3 has separate methods for library keywords, user keywords andall control structures. If there is a need to listen to all keyword relatedevents, it is possible to implementstart_keyword andend_keyword. In additionto that,start_body_item andend_body_item can be implemented to getnotifications related to all keywords and control structures. These higher levellistener methods are not called if more specific methods likestart_library_keywordorend_if are implemented.

Listener methods in the API version 3 are listed in the following tableand in the API docs of the optionalListenerV3 base class.

Methods in the listener API 3
MethodArgumentsDocumentation
start_suitedata, result

Called when a test suite starts.

data andresult are model objects representingtheexecuted test suite anditsexecution results, respectively.

end_suitedata, result

Called when a test suite ends.

Same arguments as withstart_suite.

start_testdata, result

Called when a test case starts.

data andresult are model objects representingtheexecuted test case anditsexecution results, respectively.

end_testdata, result

Called when a test case ends.

Same arguments as withstart_test.

start_keyworddata, result

Called when a keyword starts.

data andresult are model objects representingtheexecuted keyword call anditsexecution results, respectively.

This method is called, by default, with user keywords, librarykeywords and when a keyword call is invalid. It is not calledif a more specificstart_user_keyword,start_library_keywordorstart_invalid_keyword method is implemented.

end_keyworddata, result

Called when a keyword ends.

Same arguments and other semantics as withstart_keyword.

start_user_keyworddata,implementation,result

Called when a user keyword starts.

data andresult are the same as withstart_keyword andimplementation is the actually executeduser keyword.

If this method is implemented,start_keyword is not calledwith user keywords.

end_user_keyworddata,implementation,result

Called when a user keyword ends.

Same arguments and other semantics as withstart_user_keyword.

start_library_keyworddataimplementation,result

Called when a library keyword starts.

data andresult are the same as withstart_keyword andimplementation represents the executedlibrary keyword.

If this method is implemented,start_keyword is not calledwith library keywords.

end_library_keyworddata,implementation,result

Called when a library keyword ends.

Same arguments and other semantics as withstart_library_keyword.

start_invalid_keyworddataimplementation,result

Called when an invalid keyword call starts.

data andresult are the same as withstart_keyword andimplementation represents theinvalid keyword call. Keyword may not have been found,there could have been multiple matches, or the keyword callitself could have been invalid.

If this method is implemented,start_keyword is not calledwith invalid keyword calls.

end_invalid_keyworddata,implementation,result

Called when an invalid keyword call ends.

Same arguments and other semantics as withstart_invalid_keyword.

start_for,start_for_iteration,start_while,start_while_iteration,start_if,start_if_branch,start_try,start_try_branch,start_group,start_var,start_continue,start_break,start_returndata, result

Called when control structures start.

See the documentation and type hints of the optionalListenerV3 base class for more information.

end_for,end_for_iteration,end_while,end_while_iteration,end_if,end_if_branch,end_try,end_try_branch,end_group,end_var,end_continue,end_break,end_returndata, result

Called when control structures end.

See the documentation and type hints of the optionalListenerV3 base class for more information.

start_errordata, resultCalled when invalid syntax starts.
end_errordata, resultCalled when invalid syntax ends.
start_body_itemdata, resultCalled when a keyword or a control structure starts, unlessa more specific method such asstart_keyword orstart_ifis implemented.
end_body_itemdata, resultCalled when a keyword or a control structure ends, unlessa more specific method such asend_keyword orend_ifis implemented.
log_messagemessage

Called when an executed keyword writes a log message.message is a model object representing theloggedmessage.

This method is not called if the message has level belowthe currentthreshold level.

messagemessage

Called when the framework itself writes asyslog message.

message is same object as withlog_message.

library_importlibrary,importer

Called after a library has been imported.

library represents the imported library.It can be inspected and also modified.importer contains information about the location wherethe library was imported.

resource_importresource,importer

Called after a resource file has been imported.

resource represents the importedresource file. It can be inspected and also modified.importer contains information about the location wherethe resource was imported.

variables_importattrs,importer

Called after a variable file has been imported.

attrs contains information about the imported variable file asa dictionary. It can be inspected, but modifications to it have noeffect.importer contains information aboutthe location where the variable file was imported.

This method will be changed in the future so that theattrsdictionary is replaced with an object representing the importedvariable file.

output_filepath

Called when writing to anoutput file is ready.

path is an absolute path to the file as apathlib.Path objector theNone object if creating the output file is disabled.

log_filepath

Called when writing to alog file is ready.

path is an absolute path to the file as apathlib.Path object.Not called if creating the log file is disabled.

report_filepath

Called when writing to areport file is ready.

path is an absolute path to the file as apathlib.Path object.Not called if creating the report file is disabled.

xunit_filepath

Called when writing to anxunit file is ready.

path is an absolute path to the file as apathlib.Path object.Only called if creating the xunit file is enabled.

debug_filepath

Called when writing to adebug file is ready.

path is an absolute path to the file as apathlib.Path object.Only called if creating the debug file is enabled.

close 

Called when the whole test execution ends.

Withlibrary listeners called when the library goes outof scope.

Note

Methods related to keywords and control structures are new inRobot Framework 7.0.

Note

Methods related to library, resource file and variable file importsare new in Robot Framework 7.1.

Note

Prior to Robot Framework 7.0, paths passed to result file related listenerversion 3 methods were strings.

4.3.3   Taking listeners into use

Registering listeners from command line

Listeners that need to be active during the whole execution must be taken intouse from the command line. That is done using the--listener optionso that the name of the listener is given to it as an argument. The listenername is got from the name of the class or module implementing thelistener, similarly aslibrary name is got from the class or moduleimplementing the library. The specified listeners must be in the samemodulesearch path where test libraries are searched from when they are imported.In addition to registering a listener by using a name, it is possible to givean absolute or a relative path to the listener filesimilarly as with testlibraries. It is possible to take multiple listenersinto use by using this option several times:

robot --listener MyListener tests.robotrobot --listener path/to/MyListener.py tests.robotrobot --listener module.Listener --listener AnotherListener tests.robot

It is also possible to give arguments to listener classes from the commandline. Arguments are specified after the listener name (or path) using a colon(:) as a separator. If a listener is given as an absolute Windows path,the colon after the drive letter is not considered a separator.Additionally, it is possible to use a semicolon (;) as analternative argument separator. This is useful if listener argumentsthemselves contain colons, but requires surrounding the whole value withquotes on UNIX-like operating systems:

robot --listener listener.py:arg1:arg2 tests.robotrobot --listener "listener.py;arg:with:colons" tests.robotrobot --listener c:\path\listener.py;d:\first\arg;e:\second\arg tests.robot

In addition to passing arguments one-by-one as positional arguments, it ispossible to pass them using thenamed argument syntax similarly as when usingkeywords:

robot --listener listener.py:name=value tests.robotrobot --listener "listener.py;name=value:with:colons;second=argument" tests.robot

Listener arguments are automatically converted usingsame rules as withkeywords based ontype hints anddefault values. For example,this listener

classListener:def__init__(self,port:int,log=True):self.port=postself.log=log

could be used like

robot --listener Listener:8270:false

and the first argument would be converted to an integer based on the type hintand the second to a Boolean based on the default value.

Note

Both the named argument syntax and argument conversion are new inRobot Framework 4.0.

Libraries as listeners

Sometimes it is useful also fortest libraries to get notifications abouttest execution. This allows them, for example, to perform certain clean-upactivities automatically when a test suite or the whole test execution ends.

Registering listener

A test library can register a listener by using theROBOT_LIBRARY_LISTENERattribute. The value of this attribute should be an instance of the listenerto use. It may be a totally independent listener or the library itself canact as a listener. To avoid listener methods to be exposed as keywords inthe latter case, it is possible to prefix them with an underscore.For example, instead of usingend_suite it is possible to use_end_suite.

Following examples illustrates using an external listener as well as a libraryacting as a listener itself:

fromlistenerimportListenerclassLibraryWithExternalListener:ROBOT_LIBRARY_SCOPE='GLOBAL'ROBOT_LIBRARY_LISTENER=Listener()defexample_keyword(self):...
classLibraryItselfAsListener:ROBOT_LIBRARY_SCOPE='SUITE'ROBOT_LISTENER_API_VERSION=2def__init__(self):self.ROBOT_LIBRARY_LISTENER=self# Use the '_' prefix to avoid listener method becoming a keyword.def_end_suite(self,name,attrs):print(f"Suite '{name}' ending with status{attrs['id']}.")defexample_keyword(self):...

As the second example above already demonstrated, library listeners canspecifylistener interface versions using theROBOT_LISTENER_API_VERSIONattribute exactly like any other listener.

Starting from Robot Framework 7.0, a listener can register itself to be a listeneralso by using a stringSELF (case-insensitive) as a listener. This is especiallyconvenient when using the@library decorator:

fromrobot.api.decoimportkeyword,library@library(scope='SUITE',listener='SELF')classLibraryItselfAsListener:# Listener version is not specified, so uses the listener version 3 by default.# When using the @library decorator, keywords must use the @keyword decorator,# so there is no need to use the '_' prefix here.defend_suite(self,data,result):print(f"Suite '{data.name}' ending with status{result.status}.")@keyworddefexample_keyword(self):...

It is also possible to specify multiple listeners for a single library bygivingROBOT_LIBRARY_LISTENER a value as a list:

fromlistenersimportListener1,Listener2,Listener3classLibraryWithMultipleListeners:ROBOT_LIBRARY_LISTENER=[Listener1(),Listener2(),Listener3()]defexample_keyword(self):...
Called listener methods

Library listeners get notifications about all events in suites wherelibraries using them are imported. In practice this means that suite,test, keyword, control structure and log message related methods arecalled. In addition to them, theclose method is called when the librarygoes out of the scope.

If library creates a new listener instance every time when the libraryitself is instantiated, the actual listener instance to use will changeaccording to thelibrary scope.

4.3.4   Listener calling order

By default, listeners are called in the order they are taken into use so thatlisteners registered from the command line are called before library listeners.It is, however, possible to control the calling order by setting the specialROBOT_LISTENER_PRIORITY attribute to an integer or a floating point value.The bigger the number, the higher precedence the listener has and the earlierit is called. The number can be positive or negative and it is zero by default.

The custom order does not affect theclose method of library listeners, though.That method is always called when the library goes out of its scope.

Note

Controlling listener calling order is new in Robot Framework 7.1.

4.3.5   Listener examples

This section contains examples using the listener interface. First examplesillustrate getting notifications during execution and latter examples modifyexecuted tests and created results.

Getting information

The first example is implemented as a Python module. It uses thelistenerversion 2, but could equally well be implemented by using thelistenerversion 3.

"""Listener that stops execution if a test fails."""ROBOT_LISTENER_API_VERSION=2defend_test(name,attrs):ifattrs['status']=='FAIL':print(f"Test '{name}'"failed:{attrs['message']}")input("Press enter to continue.")

If the above example would be saved to, for example,PauseExecution.pyfile, it could be used from the command line like this:

robot --listener path/to/PauseExecution.py tests.robot

The next example, which still uses the listener version 2, is slightly morecomplicated. It writes all the information it gets into a text file ina temporary directory without much formatting. The filename may be givenfrom the command line, but it also has a default value. Note that in real usage,thedebug file functionality available through the command line option--debugfile is probably more useful than this example.

importos.pathimporttempfileclassExample:ROBOT_LISTENER_API_VERSION=2def__init__(self,file_name='listen.txt'):path=os.path.join(tempfile.gettempdir(),file_name)self.file=open(path,'w')defstart_suite(self,name,attrs):self.file.write("%s '%s'\n"%(name,attrs['doc']))defstart_test(self,name,attrs):tags=' '.join(attrs['tags'])self.file.write("-%s '%s' [%s ] :: "%(name,attrs['doc'],tags))defend_test(self,name,attrs):ifattrs['status']=='PASS':self.file.write('PASS\n')else:self.file.write('FAIL:%s\n'%attrs['message'])defend_suite(self,name,attrs):self.file.write('%s\n%s\n'%(attrs['status'],attrs['message']))defclose(self):self.file.close()

Modifying data and results

The following examples illustrate how to modify the executed tests and suitesas well as the execution results. All these examples require usingthelistener version 3.

Modifying executed suites and tests

Changing what is executed is as easy as modifying the model objects representingexecuted data passed to listener methods. This is illustrated by the example below thatadds a new test to each executed suite and a new keyword call to each test.

defstart_suite(data,result):data.tests.create(name='New test')defstart_test(data,result):data.body.create_keyword(name='Log',args=['Keyword added by listener!'])

This API is very similar to thepre-run modifier API that can be usedto modify suites and tests before the whole test execution starts. The mainbenefit of using the listener API is that modifications can be donedynamically based on execution results or otherwise. This allows, for example,interesting possibilities for model based testing.

Although the listener interface is not built on top of Robot Framework'sinternalvisitor interface similarly as the pre-run modifier API,listeners can still use the visitors interface themselves. For example,theSelectEveryXthTest visitor used inpre-run modifier examples couldbe used like this:

fromSelectEveryXthTestimportSelectEveryXthTestdefstart_suite(suite,result):selector=SelectEveryXthTest(x=2)suite.visit(selector)
Accessing library or resource file

It is possible to get more information about the actually executed keyword andthe library or resource file it belongs to:

fromrobot.runningimportKeywordasKeywordData,LibraryKeywordfromrobot.resultimportKeywordasKeywordResultdefstart_library_keyword(data:KeywordData,implementation:LibraryKeyword,result:KeywordResult):library=implementation.ownerprint(f"Keyword '{implementation.name}' is implemented in library "f"'{library.name}' at '{implementation.source}' on line "f"{implementation.lineno}. The library has{library.scope.name} "f"scope and the current instance is{library.instance}.")

As the above example illustrates, it is possible to get an access to the actuallibrary instance. This means that listeners can inspect the library state and alsomodify it. With user keywords it is even possible to modify the keyword itself or,via theowner resource file, any other keyword in the resource file.

Modifying results

Test execution results can be altered by modifying the result objects passed tolistener methods. This is demonstrated by the following listener that is implementedas a class and also uses type hints:

fromrobotimportresult,runningclassResultModifier:def__init__(self,max_seconds:float=10.0):self.max_seconds=max_secondsdefstart_suite(self,data:running.TestSuite,result:result.TestSuite):result.doc='Documentation set by listener.'# Information about tests only available via data at this point.smoke_tests=[testfortestindata.testsif'smoke'intest.tags]result.metadata['Smoke tests']=len(smoke_tests)defend_test(self,data:running.TestCase,result:result.TestCase):elapsed_seconds=result.elapsed_time.total_seconds()ifresult.status=='PASS'andelapsed_seconds>self.max_seconds:result.status='FAIL'result.message='Test execution took too long.'deflog_message(self,msg:result.Message):ifmsg.level=='WARN'andnotmsg.html:msg.message=f'<b style="font-size: 1.5em">{msg.message}</b>'msg.html=Trueifself._message_is_not_relevant(msg.message):msg.message=Nonedef_message_is_not_relevant(self,message:str)->bool:...

A limitation is that modifying the name of the current test suite or testcase is not possible because it has already been written to theoutput.xmlfile when listeners are called. Due to the same reason modifying alreadyfinished tests in theend_suite method has no effect either.

When modifying logged messages, it is possible to remove a message altogetherby settingmessage toNone as the above example demonstrates. This can beused for removing sensitive or non-relevant messages so that there is nothingvisible in the log file.

This API is very similar to thepre-Rebot modifier API that can be usedto modify results before report and log are generated. The main difference isthat listeners modify also the createdoutput.xml file.

Note

Removing messages altogether by setting them toNone is new inRobot Framework 7.2.

Changing keyword and control structure status

Listeners can also affect the execution flow by changing statuses of the executedkeywords and control structures. For example, if a listener changes the status ofa passed keyword to FAIL, the keyword is considered failed exactly as if it hadfailed normally. Similarly, it is possible to change the status of a passed orfailed keyword to SKIP to get the keyword and the whole test skipped. It isalso possible to silence failures by changing the status to PASS, but thisshould be done only in special cases and with great care to avoid hiding realfailures.

The following example demonstrates changing the status by failing keywordsthat take too long time to execute. The previous example had similar logicwith tests, but this listener also stops the execution immediately if thereis a keyword that is too slow. As the example shows, listeners can also changethe error message, not only the status.

fromrobotimportresult,runningclassKeywordPerformanceMonitor:def__init__(self,max_seconds:float=0.1):self.max_seconds=max_secondsdefend_keyword(self,data:running.Keyword,result:result.Keyword):elapsed_seconds=result.elapsed_time.total_seconds()ifresult.status=='PASS'andelapsed_seconds>self.max_seconds:result.status='FAIL'result.message='Keyword execution took too long.'

Note

Changes to status only affect the execution flow starting fromRobot Framework 7.1.

More examples

Keyword and control structure related listener version 3 methods are so versatilethat covering them fully here in the User Guide is not possible. For more examples,you can see theacceptance tests using theses methods in various ways.

4.4   Parser interface

Robot Framework supports external parsers that can handle custom data formats oreven override Robot Framework's own parser.

Note

Custom parsers are new in Robot Framework 6.1.

4.4.1   Taking parsers into use

Parsers are taken into use from the command line with the--parseroption using exactly the same semantics as withlisteners. This includesspecifying parsers as names or paths, giving arguments to parser classes, andso on:

robot --parser MyParser tests.customrobot --parser path/to/MyParser.py tests.customrobot --parser Parser1:arg --parser Parser2:a1:a2 path/to/tests

4.4.2   Parser API

Parsers can be implemented both as modules and classes. This section explainswhat attributes and methods they must contain.

EXTENSION orextension attribute

This attribute specifies what file extension or extensions the parser supports.BothEXTENSION andextension names are accepted, and the former has precedenceif both exist. The attribute can be either a string or a sequence of strings.Extensions are case-insensitive and can be specified with or without the leadingdot. If a parser is implemented as a class, it is possible to set this attributeeither as a class attribute or as an instance attribute.

Also extensions containing multiple parts like.example.ext or.robot.zip are supported.

Note

If a parser supports the.robot extension, it will be usedfor parsing these files instead of the standard parser.

parse method

The mandatoryparse method is responsible for parsingsuite files. It iscalled with each parsed file that has an extension that the parser supports.The method must return aTestSuite object.

In simple casesparse can be implemented so that it accepts just a singleargument that is apathlib.Path object pointing to the file toparse. If the parser is interested in defaults forTest Setup,Test Teardown,Test Tags andTest Timeoutset in higher levelsuite initialization files, theparse method mustaccept two arguments. In that case the second argument is aTestDefaults object.

parse_init method

The optionalparse_init method is responsible for parsingsuite initializationfiles i.e. files in format__init__.ext where.ext is an extensionsupported by the parser. The method must return aTestSuiteobject representing the whole directory. Suites created from child suite filesand directories will be added to its child suites.

Alsoparse_init can be implemented so that it accepts one or two arguments,depending on is it interested in test related default values or not. If itaccepts defaults, it can manipulate the passedTestDefaults object and changesare seen when parsing child suite files.

This method is only needed if a parser needs to support suite initialization files.

Optional base class

Parsers do not need to implement any explicit interface, but it may be helpfulto extend the optionalParser base class. The main benefit is that the baseclass has documentation and type hints. It also works as a bit more formal APIspecification.

4.4.3   Examples

Parser implemented as module

The first example demonstrates a simple parser implemented as a module andsupporting one hard-coded extension. It just creates a dummy suite and does notactually parse anything.

fromrobot.apiimportTestSuiteEXTENSION='.example'defparse(source):suite=TestSuite(name='Example',source=source)test=suite.tests.create(name='Test')test.body.create_keyword(name='Log',args=['Hello!'])returnsuite

Parser implemented as class

The second parser is implemented as a class that accepts the extension to useas an argument. The parser reads the given source file and creates dummy testsfrom each line it contains.

frompathlibimportPathfromrobot.apiimportTestSuiteclassExampleParser:def__init__(self,extension:str):self.extension=extensiondefparse(self,source:Path)->TestSuite:name=TestSuite.name_from_source(source,self.extension)suite=TestSuite(name,source=source)forlineinsource.read_text().splitlines():test=suite.tests.create(name=line)test.body.create_keyword(name='Log',args=['Hello!'])returnsuite

Parser extending optional base class

This parser extends the optionalParser base class. It supports parsing suiteinitialization files, usesTestDefaults and registers multiple extensions.

frompathlibimportPathfromrobot.apiimportTestSuitefromrobot.api.interfacesimportParser,TestDefaultsclassExampleParser(Parser):extension=('example','another')defparse(self,source:Path,defaults:TestDefaults)->TestSuite:"""Create a suite and set possible defaults from init files to tests."""suite=TestSuite(TestSuite.name_from_source(source),source=source)forlineinsource.read_text().splitlines():test=suite.tests.create(name=line,doc='Example')test.body.create_keyword(name='Log',args=['Hello!'])defaults.set_to(test)returnsuitedefparse_init(self,source:Path,defaults:TestDefaults)->TestSuite:"""Create a dummy suite and set some defaults.        This method is called only if there is an initialization file with        a supported extension.        """defaults.tags=('tags','from init')defaults.setup={'name':'Log','args':['Hello from init!']}returnTestSuite(TestSuite.name_from_source(source.parent),doc='Example',source=source,metadata={'Example':'Value'})

Parser as preprocessor

The final example parser acts as a preprocessor for Robot Framework data filesthat supports headers in format=== Test Cases === in addition to*** Test Cases ***. In this kind of usage it is convenient to useTestSuite.from_string,TestSuite.from_model andTestSuite.from_file_system factory methods for constructing the returned suite.

frompathlibimportPathfromrobot.runningimportTestDefaults,TestSuiteclassRobotPreprocessor:extension='.robot'defparse(self,source:Path,defaults:TestDefaults)->TestSuite:data=source.read_text()forheaderin'Settings','Variables','Test Cases','Keywords':data=data.replace(f'==={header} ===',f'***{header} ***')suite=TestSuite.from_string(data,defaults=defaults)returnsuite.config(name=TestSuite.name_from_source(source),source=source)

5   Supporting Tools

5.1   Library documentation tool (Libdoc)

Libdoc is Robot Framework's built-in tool that can generate documentation forRobot Framework libraries and resource files. It can generate HTML documentationfor humans as well as machine readable spec files in XML and JSON formats.Libdoc also has few special commands to show library or resource informationon the console.

Documentation can be created for:

Additionally it is possible to use XML and JSON spec files created by Libdocearlier as an input.

Note

Support for generating documentation for suite files and suiteinitialization files is new in Robot Framework 6.0.

5.1.1   General usage

Synopsis

libdoc [options] library_or_resource output_filelibdoc [options] library_or_resource list|show|version [names]

Options

-f,--format<html|xml|json|libspec>
 Specifies whether to generate an HTML output for humans ora machine readable spec file in XML or JSON format. Thelibspec format means XML spec with documentations convertedto HTML. The default format is got from the output fileextension.
-s,--specdocformat<raw|html>
 Specifies the documentation format used with XML and JSONspec files.raw means preserving the original documentationformat andhtml means converting documentation to HTML. Thedefault israw with XML spec files andhtml with JSONspecs and when using the speciallibspec format.
-F,--docformat<robot|html|text|rest>
 Specifies the source documentation format. Possiblevalues are Robot Framework's documentation format,HTML, plain text, and reStructuredText. Default valuecan be specified in test library source code andthe initial default value isrobot.
--theme<dark|light|none>
 Use dark or light HTML theme. If this option is not used,or the value isnone, the theme is selected based onthe browser color scheme. Only applicable with HTML outputs.New in Robot Framework 6.0.
--language<lang>
 Set the default language in documentation.langmust be a code of a built-in language, which areen andfi. New in Robot Framework 7.2.
-N,--name<newname>
 Sets the name of the documented library or resource.
-V,--version<newversion>
 Sets the version of the documented library orresource. The default value for test libraries isdefined in the source code.
-P,--pythonpath<path>
 Additional locations where to search for librariesand resources similarly as whenrunning tests.
--quietDo not print the path of the generated output fileto the console.
-h,--helpPrints this help.

Executing Libdoc

The easiest way to run Libdoc is using thelibdoc command created as part ofthe normal installation:

libdoc ExampleLibrary ExampleLibrary.html

Alternatively it is possible to execute therobot.libdoc module directly.This approach is especially useful if you have installed Robot Framework usingmultiple Python versions and want to use a specific version with Libdoc:

python -m robot.libdoc ExampleLibrary ExampleLibrary.htmlpython3.9 -m robot.libdoc ExampleLibrary ExampleLibrary.html

Yet another alternative is running therobot.libdoc module as a script:

python path/to/robot/libdoc.py ExampleLibrary ExampleLibrary.html

Note

The separatelibdoc command is new in Robot Framework 4.0.

Specifying library or resource file

Python libraries and dynamic libraries with name or path

When documenting libraries implemented with Python or that use thedynamic library API, it is possible to specify the library either byusing just the library name or path to the library source code:

libdoc ExampleLibrary ExampleLibrary.htmllibdoc src/ExampleLibrary.py docs/ExampleLibrary.html

In the former case the library is searched using themodule search pathand its name must be in the same format as whenimporting libraries inRobot Framework test data.

If these libraries require arguments when they are imported, the argumentsmust be catenated with the library name or path using two colons likeMyLibrary::arg1::arg2. If arguments change what keywords the libraryprovides or otherwise alter its documentation, it might be a good idea to use--name option to also change the library name accordingly.

Resource files with path

Resource files must always be specified using a path:

libdoc example.resource example.html

If the path does not exist, resource files are also searched from all directoriesin themodule search path similarly as when executing test cases.

Libdoc spec files

Earlier generated Libdoc XML or JSON spec files can also be used as inputs.This works if spec files use either*.xml,*.libspec or*.json extension:

libdoc Example.xml Example.htmllibdoc Example.libspec Example.htmllibdoc Example.json Example.html

Note

Support for the*.libspec extension is new inRobot Framework 3.2.

Note

Support for the*.json extension is new inRobot Framework 4.0.

Generating documentation

Libdoc can generate documentation in HTML (for humans) and XML or JSON (for tools)formats. The file where to write the documentation is specified as the secondargument after the library/resource name or path, and the output format isgot from the output file extension by default.

Libdoc HTML documentation

Most Robot Framework libraries use Libdoc to generate library documentationin HTML format. This format is thus familiar for most people who have usedRobot Framework. A simple example can be seen below, and it has been generatedbased on the example found abit later in this section.

src/SupportingTools/ExampleLibrary.png

The HTML documentation starts with general library introduction, continueswith a section about configuring the library when it is imported (whenapplicable), and finally has shortcuts to all keywords and the keywordsthemselves. The magnifying glass icon on the lower right corner opens thekeyword search dialog that can also be opened by simply pressing thes key.

Libdoc automatically creates HTML documentation if the output file extensionis*.html. If there is a need to use some other extension, theformat can be specified explicitly with the--format option.

Starting from Robot Framework 7.2, it is possible to localise the statictexts in the HTML documentation by using the--language option.

See theREADME.rst file insrc/web/libodc directory in the projectrepository for up to date information about how to add new languagesfor the localisation.

libdoc OperatingSystem OperatingSystem.htmllibdoc --name MyLibrary Remote::http://10.0.0.42:8270 MyLibrary.htmllibdoc --format HTML test/resource.robot doc/resource.htm
Libdoc XML spec files

Libdoc can also generate documentation in XML format that is suitable forexternal tools such as editors. It contains all the same information asthe HTML format but in a machine readable format.

XML spec files also contain library and keyword source information so thatthe library and each keyword can have source path (source attribute) andline number (lineno attribute). The source path is relative to the directorywhere the spec file is generated thus does not refer to a correct file ifthe spec is moved. The source path is omitted with keywords if it isthe same as with the library, and both the source path and the line numberare omitted if getting them from the library fails for whatever reason.

Libdoc automatically uses the XML format if the output file extension is*.xml or*.libspec. When using the special*.libspecextension, Libdoc automatically enables the options-f XML -s HTML which meanscreating an XML output file where keyword documentation is converted to HTML.If needed, the format can be explicitly set with the--format option.

libdoc OperatingSystem OperatingSystem.xmllibdoc test/resource.robot doc/resource.libspeclibdoc --format xml MyLibrary MyLibrary.speclibdoc --format xml -s html MyLibrary MyLibrary.xml

The exact Libdoc spec file format is documented with anXML schema (XSD)athttps://github.com/robotframework/robotframework/tree/master/doc/schema.The spec file format may change between Robot Framework major releases.

To make it easier for external tools to know how to parse a certainspec file, the spec file root element has a dedicatedspecversionattribute. It was added in Robot Framework 3.2 with value2 and earlierspec files can be considered to have version1. The spec version willbe incremented in the future if and when changes are made.Robot Framework 4.0 introduced new spec version3 which is incompatiblewith earlier versions.

Note

TheXML:HTML format introduced in Robot Framework 3.2. has beenreplaced by the formatLIBSPEC ot the option combination--format XML --specdocformat HTML.

Note

Including source information and spec version are new in RobotFramework 3.2.

Libdoc JSON spec files

Since Robot Framework 4.0 Libdoc can also generate documentation in JSONformat that is suitable for external tools such as editors or web pages.It contains all the same information as the HTML format but in a machinereadable format.

Similar to XML spec files the JSON spec files contain all information andcan also be used as input to Libdoc. From that format any other output formatcan be created. By default the library documentation strings are convertedto HTML format within the JSON output file.

The exact JSON spec file format is documented with anJSON schemaathttps://github.com/robotframework/robotframework/tree/master/doc/schema.The spec file format may change between Robot Framework major releases.

Viewing information on console

Libdoc has three special commands to show information on the console.These commands are used instead of the name of the output file, and they canalso take additional arguments.

list
List names of the keywords the library/resource contains. Can belimited to show only certain keywords by passing optional patternsas arguments. Keyword is listed if its name contains given pattern.
show
Show library/resource documentation. Can be limited to show onlycertain keywords by passing names as arguments. Keyword is shown ifits name matches any given name. Special argumentintro will showonly the library introduction and importing sections.
version
Show library version

Optional patterns given tolist andshow are case and spaceinsensitive. Both also accept* and? as wildcards.

Examples:

libdoc Dialogs listlibdoc SeleniumLibrary list browserlibdoc Remote::10.0.0.42:8270 showlibdoc Dialogs show PauseExecution execute*libdoc SeleniumLibrary show introlibdoc SeleniumLibrary version

5.1.2   Writing documentation

This section discusses writing documentation forPython based testlibraries that use the static library API as well as fordynamic librariesandresource files.Creating test libraries andresource files isdescribed in more details elsewhere in the User Guide.

Python libraries

The documentation for Python libraries that use thestatic library APIis written simply as doc strings for the library class or module and formethods implementing keywords. The first line of the method documentation isconsidered as a short documentation for the keyword (used, for example, asa tool tip in links in the generated HTML documentation), and it shouldthus be as describing as possible, but not too long.

The simple example below illustrates how to write the documentation ingeneral. How the HTML documentation generated based on this example lookslike can be seenabove, and there is also abit longer example atthe end of this chapter.

classExampleLibrary:"""Library for demo purposes.    This library is only used in an example and it doesn't do anything useful.    """defmy_keyword(self):"""Does nothing."""passdefyour_keyword(self,arg):"""Takes one argument and *does nothing* with it.        Examples:        | Your Keyword | xxx |        | Your Keyword | yyy |        """pass

Tip

If you library does some initialization work that should not be donewhen using Libdoc, you caneasily detect is Robot Framework running

Tip

For more information on Python documentation strings, seePEP-257.

Dynamic libraries

To be able to generate meaningful documentation for dynamic libraries,the libraries must return keyword argument names and documentation usingget_keyword_arguments andget_keyword_documentationmethods (or using their camelCase variantsgetKeywordArgumentsandgetKeywordDocumentation). Libraries can also supportgeneral library documentation via special__intro__ and__init__ values to theget_keyword_documentation method.

See theDynamic library API section for more information about how tocreate these methods.

Importing section

A separate section about how the library is imported is created based on itsinitialization methods. If the library has an__init__method that takes arguments in addition toself, its documentation andarguments are shown.

classTestLibrary:def__init__(self,mode='default')"""Creates new TestLibrary. `mode` argument is used to determine mode."""self.mode=modedefsome_keyword(self,arg):"""Does something based on given `arg`.        What is done depends on the `mode` specified when `importing` the library.        """ifself.mode=='secret':# ...

Resource file documentation

Keywords in resource files can have documentation using[Documentation] setting, and this documentation is also used byLibdoc. First line of the documentation (until the firstimplicit newline or explicit\n) is considered to be the shortdocumentation similarly as with test libraries.

Also the resource file itself can haveDocumentation in theSetting section for documenting the whole resource file.

Possible variables in resource files can not be documented.

*** Settings ***DocumentationResource file for demo purposes....This resource is only used in an example and it doesn't do anything useful.*** Keywords ***My Keyword    [Documentation]Does nothingNo OperationYour Keyword    [Arguments]  ${arg}    [Documentation]Takes one argument and *does nothing* with it.    ...    ...Examples:    ...| Your Keyword | xxx |    ...| Your Keyword | yyy |No Operation

5.1.3   Documentation syntax

Libdoc supports documentation in Robot Framework's owndocumentationsyntax, HTML, plain text, andreStructuredText. The format to use can bespecified inlibrary source code usingROBOT_LIBRARY_DOC_FORMATattribute or given from the command line using--docformat (-F) option.In both cases the possible case-insensitive values areROBOT (default),HTML,TEXT andreST.

Robot Framework's own documentation format is the default and generallyrecommended format. Other formats are especially useful when using existingcode with existing documentation in test libraries.

Robot Framework documentation syntax

Most important features in Robot Framework'sdocumentation syntax areformatting using*bold* and_italic_, custom links andautomatic conversion of URLs to links, and the possibility to create tables andpre-formatted text blocks (useful for examples) simply with pipe character.If documentation gets longer, support for section titles can also be handy.

Some of the most important formatting features are illustrated in the examplebelow. Notice that since this is the default format, there is no need to useROBOT_LIBRARY_DOC_FORMAT attribute nor give the format from the commandline.

"""Example library in Robot Framework format.- Formatting with *bold* and _italic_.- URLs like http://example.com are turned to links.- Custom links like [http://robotframework.org|Robot Framework] are supported.- Linking to `My Keyword` works."""defmy_keyword():"""Nothing more to see here."""
Creating table of contents automatically

With bigger libraries it is often useful to add a table of contents tothe library introduction. When using the Robot Framework documentation format,this can be done automatically by adding a special%TOC% marker into a lineon its own. The table of contents is created based on the top-levelsection titles (e.g.= Section =) used in the introduction. In additionto them, the TOC also gets links to theautomatically created sectionsfor shortcuts and keywords as well as for importing and tags sections whenapplicable.

"""Example library demonstrating TOC generation.The %TOC% marker only creates the actual table of contents and possibleheader or other explanation needs to be added separately like done below.== Table of contents ==%TOC%= Section title =The top-level section titles are automatically added to the TOC.= Second section === Sub section ==Sub section titles are not added to the TOC."""defmy_keyword():"""Nothing more to see here."""

Note

Automatic TOC generation is a new feature in Robot Framework 3.2.

HTML documentation syntax

When using HTML format, you can create documentation pretty much freely usingany syntax. The main drawback is that HTML markup is not that human friendly,and that can make the documentation in the source code hard to maintain and read.Documentation in HTML format is used by Libdoc directly without anytransformation or escaping. The special syntax forlinking to keywords usingsyntax like`My Keyword` is supported, however.

Example below contains the same formatting examples as the previous example.NowROBOT_LIBRARY_DOC_FORMAT attribute must be used or format givenon the command line like--docformat HTML.

"""Example library in HTML format.<ul>  <li>Formatting with <b>bold</b> and <i>italic</i>.  <li>URLs are not turned to links automatically.  <li>Custom links like <a href="http://www.w3.org/html">HTML</a> are supported.  <li>Linking to `My Keyword` works.</ul>"""ROBOT_LIBRARY_DOC_FORMAT='HTML'defmy_keyword():"""Nothing more to see here."""

Plain text documentation syntax

When the plain text format is used, Libdoc uses the documentation as-is.Newlines and other whitespace are preserved except for indentation, andHTML special characters (<>&) escaped. The only formatting done isturning URLs into clickable links and supportinginternal linkinglike`My Keyword`.

"""Example library in plain text format.- Formatting is not supported.- URLs like http://example.com are turned to links.- Custom links are not supported.- Linking to `My Keyword` works."""ROBOT_LIBRARY_DOC_FORMAT='text'defmy_keyword():"""Nothing more to see here."""

reStructuredText documentation syntax

reStructuredText is simple yet powerful markup syntax used widely in Pythonprojects (including this User Guide) and elsewhere. The main limitationis that you need to have thedocutils module installed to be able to generatedocumentation using it. Because backtick characters have special meaning inreStructuredText,linking to keywords requires them to be escaped like\`My Keyword\`.

One of the nice features that reStructured supports is the ability to mark codeblocks that can be syntax highlighted.Syntax highlight requires additionalPygments module and supports all thelanguages that Pygments supports.

"""Example library in reStructuredText format.- Formatting with **bold** and *italic*.- URLs like http://example.com are turned to links.- Custom links like reStructuredText__ are supported.- Linking to \`My Keyword\` works but requires backtics to be escaped.__ http://docutils.sourceforge.net.. code:: robotframework    *** Test Cases ***    Example        My keyword    # How cool is this!!?!!?!1!!"""ROBOT_LIBRARY_DOC_FORMAT='reST'defmy_keyword():"""Nothing more to see here."""

5.1.4   Internal linking

Libdoc supports internal linking to keywords and differentsections in the documentation. Linking is done by surrounding thetarget name with backtick characters like`target`. Targetnames are case-insensitive and possible targets are explained in thesubsequent sections.

There is no error or warning if a link target is not found, but instead Libdocjust formats the text in italics. Earlier this formatting was recommended tobe used when referring to keyword arguments, but that was problematic becauseit could accidentally create internal links. Nowadays it is recommended touseinline code style with double backticks like``argument`` instead. The old formatting of single backticksmay even be removed in the future in favor of giving an error when a linktarget is not found.

In addition to the examples in the following sections, internal linkingand argument formatting is shown also in thelonger example at theend of this chapter.

Linking to keywords

All keywords the library have automatically create link targets and they canbe linked using syntax`Keyword Name`. This is illustrated withthe example below where both keywords have links to each others.

defkeyword(log_level="INFO"):"""Does something and logs the output using the given level.    Valid values for log level` are "INFO" (default) "DEBUG" and "TRACE".    See also `Another Keyword`.    """# ...defanother_keyword(argument,log_level="INFO"):"""Does something with the given argument else and logs the output.    See `Keyword` for information about valid log levels.    """# ...

Note

When usingreStructuredText documentation syntax, backticks mustbe escaped like\`Keyword Name\`.

Linking to automatic sections

The documentation generated by Libdoc always contains sectionsfor overall library introduction and forkeywords. If a library itself takes arguments, there is alsoseparateimporting section. If any of the keywords hastags,a separate selector for them is also shown in the overview.

All the sections act as targets that can be linked, and the possibletarget names are listed in the table below. Using these targets isshown in the example of the next section.

Automatic section link targets
SectionTarget
Introduction`introduction` and`library introduction`
Importing`importing` and`library importing`
Keywords`keywords`

Note

Before Robot Framework 4.0 there were also sections for tags and shortcuts.In Robot Framework 4.0 these have been removed in favor of the overview menu. This meansthat prior linking to shortcuts or tags sections does not work.

Linking to custom sections

Robot Framework'sdocumentation syntaxsupports customsection titles, and the titles used in thelibrary or resource file introduction automatically create linktargets. The example below illustrates linking both to automatic andcustom sections:

"""Library for Libdoc demonstration purposes.This library does not do anything useful.= My section  =We do have a custom section in the documentation, though."""defkeyword():"""Does nothing.    See `introduction` for more information and `My section` to test how    linking to custom sections works.    """pass

Note

Linking to custom sections works only when usingRobot Frameworkdocumentation syntax.

5.1.5   Representing arguments

Libdoc shows information about keywords' arguments automatically.

Included information

The following information is shown for all keywords regardless are they implementedin libraries or in resource files:

  • Argument name. User keyword arguments are shown without the${} decorationto make arguments look the same regardless where keywords originate from.
  • Marker telling is the argumentpositional-only,named-only,free positional,free named, ornormal argument that can be giveneither by position or by name.
  • Possible default value. Shown like= 42.
  • Possible type. Shown like<int>. Can be a link to type documentation as explainedin the next section.

When referring to arguments in keyword documentation, it is recommended touseinline code style like``argument``.

Automatically listing type documentation

As mentioned above, Libdoc automatically shows possible type information whenlisting arguments. If the type is a custom type based onEnum orTypedDict,the type isautomatically converted, or the type hascustom converter,also the type itself is listed separately to show more information about it.When these types are used in arguments, the type name also becomes a linkto the type information.

All listed data types show possible type documentation as well as what argumenttypes are supported. In addition to that, types based onEnum list availablemembers and types based onTypedDict show the dictionary structure.

Note

Automatically listing types based onEnum andTypedDict is newin Robot Framework 4.0. Listing other types is new in Robot Framework 5.0.

5.1.6   Libdoc example

The following example illustrates how to use the most importantdocumentation formatting possibilities,internal linking, and soon.Click here to see how the generated documentation looks like.

classLoggingLibrary:"""Library for logging messages.    = Table of contents =    %TOC%    = Usage =    This library has several keyword, for example `Log Message`, for logging    messages. In reality the library is used only for _Libdoc_ demonstration    purposes.    = Valid log levels =    Valid log levels are ``INFO``, ``DEBUG``, and ``TRACE``. The default log    level can be set during `importing`.    = Examples =    Notice how keywords are linked from examples.    | `Log Message`      | My message    |                |               |    | `Log Two Messages` | My message    | Second message | level=DEBUG   |    | `Log Messages`     | First message | Second message | Third message |    """ROBOT_LIBRARY_VERSION='0.1'def__init__(self,default_level='INFO'):"""The default log level can be given at library import time.        See `Valid log levels` section for information about available log        levels.        Examples:        | =Setting= |     =Value=    | =Value= |          =Comment=         |        | Library   | LoggingLibrary |         | # Use default level (INFO) |        | Library   | LoggingLibrary | DEBUG   | # Use the given level      |        """self.default_level=self._verify_level(default_level)def_verify_level(self,level):level=level.upper()iflevelnotin['INFO','DEBUG','TRACE']:raiseRuntimeError("Invalid log level'%s'. Valid levels are ""'INFO', 'DEBUG', and 'TRACE'")returnleveldeflog_message(self,message,level=None):"""Writes given message to the log file using the specified log level.        The message to log and the log level to use are defined using        ``message`` and ``level`` arguments, respectively.        If no log level is given, the default level given during `library        importing` is used.        """level=self._verify_level(level)iflevelelseself.default_levelprint("*%s*%s"%(level,message))deflog_two_messages(self,message1,message2,level=None):"""Writes given messages to the log file using the specified log level.        See `Log Message` keyword for more information.        """self.log_message(message1,level)self.log_message(message2,level)deflog_messages(self,*messages):"""Logs given messages using the log level set during `importing`.        See also `Log Message` and `Log Two Messages`.        """formsginmessages:self.log_message(msg)

Allstandard libraries have documentation generated byLibdoc and their documentation (and source code) act as a morerealistic examples.

5.2   Test data documentation tool (Testdoc)

Testdoc is Robot Framework's built-in tool for generating high leveldocumentation based on test cases. The created documentation is in HTMLformat and it includes name, documentation and other metadata of eachtest suite and test case, as well as the top-level keywords and theirarguments.

5.2.1   General usage

Synopsis

python -m robot.testdoc [options] data_sources output_file

Options

-T,--title<title>
 Set the title of the generated documentation.Underscores in the title are converted to spaces.The default title is the name of the top level suite.
-N,--name<name>
 Override the name of the top level test suite.
-D,--doc<doc>
 Override the documentation of the top level test suite.
-M,--metadata<name:value>
 Set/override free metadata of the top level test suite.
-G,--settag<tag>
 Set given tag(s) to all test cases.
-t,--test<name>
 Include tests by name.
-s,--suite<name>
 Include suites by name.
-i,--include<tag>
 Include tests by tags.
-e,--exclude<tag>
 Exclude tests by tags.
-A,--argumentfile<path>
 Text file to read more arguments from. Worksexactly likeargument files when runningtests.
-h,--helpPrint this help in the console.

All options except--title have exactly the same semantics as sameoptions have whenexecuting test cases.

5.2.2   Generating documentation

Data can be given as a single file, directory, or as multiple files anddirectories. In all these cases, the last argument must be the file whereto write the output.

Testdoc can be executed as an installed module likepython -m robot.testdoc or as a script likepython path/robot/testdoc.py.

Examples:

python -m robot.testdoc my_test.robot testdoc.htmlpython path/to/robot/testdoc.py --name "Smoke tests" --include smoke path/to/tests smoke.html

5.3   Test data clean-up tool (Tidy)

The built-in Tidy tool was deprecated in Robot Framework 4.1 in favor of thenew and enhanced externalRobotidy tool. It was removed altogether inRobot Framework 5.0.

5.4   External tools

There are plenty of external tools that can be used with Robot Framework.These tools include plugins for various IDEs and text editors, tools forparallel execution and data-driven testing, plugins for continuous integrationsystems, and so on.

These tools are developed as separate projects independently from RobotFramework itself. For a list of the available tools seehttp://robotframework.org/.

6   Appendices

6.1   Available settings

This appendix lists all settings that can be used in different sections.

Note

Settings can belocalized. See theTranslations appendix forsupported translations.

6.1.1   Setting section

The Setting section is used to import libraries, resource files andvariable files and to define metadata for test suites and testcases. It can be included in test case files and resource files. Notethat in a resource file, a Setting section can only include settings forimporting libraries, resources, and variables.

Settings available in the Setting section
NameDescription
LibraryUsed forimporting libraries.
ResourceUsed fortaking resource files into use.
VariablesUsed fortaking variable files into use.
NameUsed for setting a customsuite name.
DocumentationUsed for specifying asuite orresource file documentation.
MetadataUsed for settingfree suite metadata.
Suite SetupUsed for specifying thesuite setup.
Suite TeardownUsed for specifying thesuite teardown.
Test TagsUsed for specifyingtest case tags for all testsin a suite.
Force Tags,Default TagsDeprecated settings for specifying test case tags.
Keyword TagsUsed for specifyinguser keyword tags for allkeywords in a certain file.
Test SetupUsed for specifying a defaulttest setup.
Test TeardownUsed for specifying a defaulttest teardown.
Test TemplateUsed for specifying a defaulttemplate keywordfor test cases.
Test TimeoutUsed for specifying a defaulttest case timeout.
Task Setup,Task Teardown,Task Template,Task TimeoutAliases for Test Setup, Test Teardown, Test Templateand Test Timeout, respectively, that can be used whencreating tasks.

6.1.2   Test Case section

The settings in the Test Case section are always specific to the testcase for which they are defined. Some of these settings override thedefault values defined in the Settings section.

Exactly same settings are available whencreating tasks in the Task section.

Settings available in the Test Case section
NameDescription
[Documentation]Used for specifying atest case documentation.
[Tags]Used fortagging test cases.
[Setup]Used for specifying atest setup.
[Teardown]Used for specifying atest teardown.
[Template]Used for specifying atemplate keyword.
[Timeout]Used for specifying atest case timeout.

6.1.3   Keyword section

Settings in the Keyword section are specific to the user keyword forwhich they are defined.

Settings available in the Keyword section
NameDescription
[Documentation]Used for specifying auser keyword documentation.
[Tags]Used for specifyinguser keyword tags.
[Arguments]Used for specifyinguser keyword arguments.
[Setup]Used for specifying auser keyword setup.New in Robot Framework 7.0.
[Teardown]Used for specifyinguser keyword teardown.
[Timeout]Used for specifying auser keyword timeout.
[Return]Used for specifyinguser keyword return values.Deprecated in Robot Framework 7.0. Use theRETURNstatement instead.

6.2   Command line options

This appendix lists all the command line options that are availablewhenexecuting test cases and whenpost-processing outputs.Also environment variables affecting execution and post-processingare listed.

6.2.1   Command line options for test execution

--rpaTurn ongeneric automation mode.
--language<lang>
 Activatelocalization.lang can be a name or a codeof abuilt-in language, or a pathor a module name of a custom language file.
-F,--extension<value>
 Parse only these files when executing a directory.
-I,--parseinclude<pattern>
 Parse only matching files when executing a directory.
-N,--name<name>
 Sets the name of the top-level test suite.
-D,--doc<document>
 Sets the documentation of the top-level test suite.
-M,--metadata<name:value>
 Sets free metadata for the top level test suite.
-G,--settag<tag>
 Sets the tag(s) to all executed test cases.
-t,--test<name>
 Selects the test cases by name.
--task<name>Alias for--test that can be used whenexecuting tasks.
-s,--suite<name>
 Selects the test suites by name.
-R,--rerunfailed<file>
 Selects failed tests from an earlieroutput fileto be re-executed.
-S,--rerunfailedsuites<file>
 Selects failed test suites from an earlieroutput file to be re-executed.
-i,--include<tag>
 Selects the test cases by tag.
-e,--exclude<tag>
 Selects the test cases by tag.
--skip<tag>Tests having given tag will beskipped. Tag can be a pattern.
--skiponfailure<tag>
 Tests having given tag will beskipped if they fail.
-v,--variable<name:value>
 Setsindividual variables.
-V,--variablefile<path:args>
 Sets variables usingvariable files.
-d,--outputdir<dir>
 Defines where tocreate output files.
-o,--output<file>
 Sets the path to the generatedoutput file.
--legacyoutputCreates output file inRobot Framework 6.x compatible format.
-l,--log<file>
 Sets the path to the generatedlog file.
-r,--report<file>
 Sets the path to the generatedreport file.
-x,--xunit<file>
 Sets the path to the generatedxUnit compatible result file.
-b,--debugfile<file>
 Adebug file that is written during execution.
-T,--timestampoutputs
 Adds a timestamp tooutput files listed above.
--splitlogSplit log file into smaller pieces that open inbrowser transparently.
--logtitle<title>
 Sets a title for the generated test log.
--reporttitle<title>
 Sets a title for the generated test report.
--reportbackground<colors>
 Sets background colors of the generated report.
--maxerrorlines<lines>
 Sets the number oferror lines shown in report when tests fail.
--maxassignlength<characters>
 Sets the number of characters shown in log whenvariables are assigned.
-L,--loglevel<level>
 Sets the threshold level for logging. Optionallythe defaultvisible log level can be givenseparated with a colon (:).
--suitestatlevel<level>
 Defines how manylevels to show in theStatistics by Suite table in outputs.
--tagstatinclude<tag>
 Includes only these tags in theStatistics by Tag table.
--tagstatexclude<tag>
 Excludes these tags from theStatistics by Tag table.
--tagstatcombine<tags:title>
 Createscombined statistics based on tags.
--tagdoc<pattern:doc>
 Addsdocumentation to the specified tags.
--tagstatlink<pattern:link:title>
 Addsexternal links to theStatistics by Tag table.
--expandkeywords<name:pattern|tag:pattern>
 Automaticallyexpand keywordsin the generated log file.
--removekeywords<all|passed|name:pattern|tag:pattern|for|while|wuks>
 Removes keyword datafrom the generated log file.
--flattenkeywords<for|while|iteration|name:pattern|tag:pattern>
 Flattens keywordsin the generated log file.
--listener<name:args>
 Sets a listener for monitoring test execution.
--nostatusrcSets thereturn code to zero regardless of failuresin test cases. Error codes are returned normally.
--runemptysuite
 Executes tests also if the selectedtest suites are empty.
--dryrunIn thedry run mode tests are run without executingkeywords originating from test libraries. Useful forvalidating test data syntax.
-X,--exitonfailure
 Stops test executionif any test fails.
--exitonerrorStops test executionif any error occurs when parsing test data, importing libraries, and so on.
--skipteardownonexit
 Skips teardowns if test execution is prematurely stopped.
--prerunmodifier<name:args>
 Activateprogrammatic modification of test data.
--prerebotmodifier<name:args>
 Activateprogrammatic modification of results.
--randomize<all|suites|tests|none>
 Randomizes test execution order.
--console<verbose|dotted|quiet|none>
 Console output type.
--dottedShortcut for--console dotted.
--quietShortcut for--console quiet.
-W,--consolewidth<width>
 Sets the width of the console output.
-C,--consolecolors<auto|on|ansi|off>
 Specifies are colors used on the console.
--consolelinks<auto|off>
 Controlsmaking paths to results files hyperlinks.
-K,--consolemarkers<auto|on|off>
 Showmarkers on the console when top levelkeywords in a test case end.
-P,--pythonpath<path>
 Additional locations to add to themodule search path.
-A,--argumentfile<path>
 A text file toread more arguments from.
-h,--helpPrintsusage instructions.
--versionPrints theversion information.

6.2.2   Command line options for post-processing outputs

--rpaTurn ongeneric automation mode.
-R,--mergeChanges result combining behavior tomerging.
-N,--name<name>
 Sets the name of the top level test suite.
-D,--doc<document>
 Sets the documentation of the top-level test suite.
-M,--metadata<name:value>
 Sets free metadata for the top-level test suite.
-G,--settag<tag>
 Sets the tag(s) to all processed test cases.
-t,--test<name>
 Selects the test cases by name.
--task<name>Alias for--test.
-s,--suite<name>
 Selects the test suites by name.
-i,--include<tag>
 Selects the test cases by tag.
-e,--exclude<tag>
 Selects the test cases by tag.
-d,--outputdir<dir>
 Defines where tocreate output files.
-o,--output<file>
 Sets the path to the generatedoutput file.
--legacyoutputCreates output file inRobot Framework 6.x compatible format.
-l,--log<file>
 Sets the path to the generatedlog file.
-r,--report<file>
 Sets the path to the generatedreport file.
-x,--xunit<file>
 Sets the path to the generatedxUnit compatible result file.
-T,--timestampoutputs
 Adds a timestamp tooutput files listed above.
--splitlogSplit log file into smaller pieces that open inbrowser transparently.
--logtitle<title>
 Sets a title for the generated test log.
--reporttitle<title>
 Sets a title for the generated test report.
--reportbackground<colors>
 Sets background colors of the generated report.
-L,--loglevel<level>
 Sets the threshold level to select log messages.Optionally the defaultvisible log level can be givenseparated with a colon (:).
--suitestatlevel<level>
 Defines how manylevels to show in theStatistics by Suite table in outputs.
--tagstatinclude<tag>
 Includes only these tags in theStatistics by Tag table.
--tagstatexclude<tag>
 Excludes these tags from theStatistics by Tag table.
--tagstatcombine<tags:title>
 Createscombined statistics based on tags.
--tagdoc<pattern:doc>
 Addsdocumentation to the specified tags.
--tagstatlink<pattern:link:title>
 Addsexternal links to theStatistics by Tag table.
--expandkeywords<name:pattern|tag:pattern>
 Automaticallyexpand keywordsin the generated log file.
--removekeywords<all|passed|name:pattern|tag:pattern|for|wuks>
 Removes keyword datafrom the generated outputs.
--flattenkeywords<for|foritem|name:pattern|tag:pattern>
 Flattens keywordsin the generated outputs.
--starttime<timestamp>
 Sets thestarting time of test execution when creatingreports.
--endtime<timestamp>
 Sets theending time of test execution when creating reports.
--nostatusrcSets thereturn code to zero regardless of failuresin test cases. Error codes are returned normally.
--processemptysuite
 Processes output files even if files containempty test suites.
--prerebotmodifier<name:args>
 Activateprogrammatic modification of results.
-C,--consolecolors<auto|on|ansi|off>
 Specifies are colors used on the console.
--consolelinks<auto|off>
 Controlsmaking paths to results files hyperlinks.
-P,--pythonpath<path>
 Additional locations to add to themodule search path.
-A,--argumentfile<path>
 A text file toread more arguments from.
-h,--helpPrintsusage instructions.
--versionPrints theversion information.

6.2.3   Environment variables for execution and post-processing

ROBOT_OPTIONS andREBOT_OPTIONS
Space separated list of default options to be placedin front of any explicit options on the command line.
ROBOT_SYSLOG_FILE
Path to asyslog file where Robot Framework writes internalinformation about parsing test case files and runningtests.
ROBOT_SYSLOG_LEVEL
Log level to use when writing to thesyslog file.
ROBOT_INTERNAL_TRACES
When set to any non-empty value, Robot Framework'sinternal methods are included inerror tracebacks.

6.3   Translations

Robot Framework supports translatingsection headers,settings,Given/When/Then prefixes used in Behavior Driven Development (BDD)as well astrue and false strings used in automatic Boolean argumentconversion. This appendix lists all translations for all languages,excluding English, that Robot Framework supports out-of-the-box.

How to actually activate translations is explained in theLocalization section.That section also explains how to create custom language definitions andhow to contribute new translations.

6.3.1   Arabic (ar)

New in Robot Framework 7.3.

Section headers

HeaderTranslation
Settingsالإعدادات
Variablesالمتغيرات
Test Casesوضعيات الاختبار
Tasksالمهام
Keywordsالأوامر
Commentsالتعليقات

Settings

SettingTranslation
Libraryالمكتبة
Resourceالمورد
Variablesالمتغيرات
Nameالاسم
Documentationالتوثيق
Metadataالبيانات الوصفية
Suite Setupإعداد المجموعة
Suite Teardownتفكيك المجموعة
Test Setupتهيئة الاختبار
Task Setupتهيئة المهمة
Test Teardownتفكيك الاختبار
Task Teardownتفكيك المهمة
Test Templateقالب الاختبار
Task Templateقالب المهمة
Test Timeoutمهلة الاختبار
Task Timeoutمهلة المهمة
Test Tagsعلامات الاختبار
Task Tagsعلامات المهمة
Keyword Tagsعلامات الأوامر
Tagsالعلامات
Setupإعداد
Teardownتفكيك
Templateقالب
Timeoutالمهلة الزمنية
Argumentsالمعطيات

BDD prefixes

PrefixTranslation
Givenبافتراض
Whenعندما, لما
Thenإذن, عندها
Andو
Butلكن

Boolean strings

True/FalseValues
Trueنعم, صحيح
Falseلا, خطأ

6.3.2   Bulgarian (bg)

Section headers

HeaderTranslation
SettingsНастройки
VariablesПроменливи
Test CasesТестови случаи
TasksЗадачи
KeywordsКлючови думи
CommentsКоментари

Settings

SettingTranslation
LibraryБиблиотека
ResourceРесурс
VariablesПроменлива
Name 
DocumentationДокументация
MetadataМетаданни
Suite SetupПървоначални настройки на комплекта
Suite TeardownПриключване на комплекта
Test SetupПървоначални настройки на тестове
Task SetupПървоначални настройки на задачи
Test TeardownПриключване на тестове
Task TeardownПриключване на задачи
Test TemplateШаблон за тестове
Task TemplateШаблон за задачи
Test TimeoutТаймаут за тестове
Task TimeoutТаймаут за задачи
Test TagsЕтикети за тестове
Task TagsЕтикети за задачи
Keyword TagsЕтикети за ключови думи
TagsЕтикети
SetupПървоначални настройки
TeardownПриключване
TemplateШаблон
TimeoutТаймаут
ArgumentsАргументи

BDD prefixes

PrefixTranslation
GivenВ случай че
WhenКогато
ThenТогава
AndИ
ButНо

Boolean strings

True/FalseValues
TrueВярно, Да, Включен
FalseНевярно, Не, Изключен, Нищо

6.3.3   Bosnian (bs)

Section headers

HeaderTranslation
SettingsPostavke
VariablesVarijable
Test CasesTest Cases
TasksTaskovi
KeywordsKeywords
CommentsKomentari

Settings

SettingTranslation
LibraryBiblioteka
ResourceResursi
VariablesVarijable
Name 
DocumentationDokumentacija
MetadataMetadata
Suite SetupSuite Postavke
Suite TeardownSuite Teardown
Test SetupTest Postavke
Task SetupTask Postavke
Test TeardownTest Teardown
Task TeardownTask Teardown
Test TemplateTest Template
Task TemplateTask Template
Test TimeoutTest Timeout
Task TimeoutTask Timeout
Test TagsTest Tagovi
Task TagsTask Tagovi
Keyword TagsKeyword Tagovi
TagsTagovi
SetupPostavke
TeardownTeardown
TemplateTemplate
TimeoutTimeout
ArgumentsArgumenti

BDD prefixes

PrefixTranslation
GivenUslovno
WhenKada
ThenTada
AndI
ButAli

Boolean strings

True/FalseValues
True 
False 

6.3.4   Czech (cs)

Section headers

HeaderTranslation
SettingsNastavení
VariablesProměnné
Test CasesTestovací případy
TasksÚlohy
KeywordsKlíčová slova
CommentsKomentáře

Settings

SettingTranslation
LibraryKnihovna
ResourceZdroj
VariablesProměnná
NameNázev
DocumentationDokumentace
MetadataMetadata
Suite SetupPříprava sady
Suite TeardownUkončení sady
Test SetupPříprava testu
Task SetupPříprava úlohy
Test TeardownUkončení testu
Task TeardownUkončení úlohy
Test TemplateŠablona testu
Task TemplateŠablona úlohy
Test TimeoutČasový limit testu
Task TimeoutČasový limit úlohy
Test TagsŠtítky testů
Task TagsŠtítky úloh
Keyword TagsŠtítky klíčových slov
TagsŠtítky
SetupPříprava
TeardownUkončení
TemplateŠablona
TimeoutČasový limit
ArgumentsArgumenty

BDD prefixes

PrefixTranslation
GivenPokud
WhenKdyž
ThenPak
AndA
ButAle

Boolean strings

True/FalseValues
TruePravda, Ano, Zapnuto
FalseNepravda, Ne, Vypnuto, Nic

6.3.5   German (de)

Section headers

HeaderTranslation
SettingsEinstellungen
VariablesVariablen
Test CasesTestfälle
TasksAufgaben
KeywordsSchlüsselwörter
CommentsKommentare

Settings

SettingTranslation
LibraryBibliothek
ResourceRessource
VariablesVariablen
NameName
DocumentationDokumentation
MetadataMetadaten
Suite SetupSuitevorbereitung
Suite TeardownSuitenachbereitung
Test SetupTestvorbereitung
Task SetupAufgabenvorbereitung
Test TeardownTestnachbereitung
Task TeardownAufgabennachbereitung
Test TemplateTestvorlage
Task TemplateAufgabenvorlage
Test TimeoutTestzeitlimit
Task TimeoutAufgabenzeitlimit
Test TagsTestmarker
Task TagsAufgabenmarker
Keyword TagsSchlüsselwortmarker
TagsMarker
SetupVorbereitung
TeardownNachbereitung
TemplateVorlage
TimeoutZeitlimit
ArgumentsArgumente

BDD prefixes

PrefixTranslation
GivenAngenommen
WhenWenn
ThenDann
AndUnd
ButAber

Boolean strings

True/FalseValues
TrueWahr, Ja, An, Ein
FalseFalsch, Nein, Aus, Unwahr

6.3.6   Spanish (es)

Section headers

HeaderTranslation
SettingsConfiguraciones
VariablesVariables
Test CasesCasos de prueba
TasksTareas
KeywordsPalabras clave
CommentsComentarios

Settings

SettingTranslation
LibraryBiblioteca
ResourceRecursos
VariablesVariable
NameNombre
DocumentationDocumentación
MetadataMetadatos
Suite SetupConfiguración de la Suite
Suite TeardownDesmontaje de la Suite
Test SetupConfiguración de prueba
Task SetupConfiguración de tarea
Test TeardownDesmontaje de la prueba
Task TeardownDesmontaje de tareas
Test TemplatePlantilla de prueba
Task TemplatePlantilla de tareas
Test TimeoutTiempo de espera de la prueba
Task TimeoutTiempo de espera de las tareas
Test TagsEtiquetas de la prueba
Task TagsEtiquetas de las tareas
Keyword TagsEtiquetas de palabras clave
TagsEtiquetas
SetupConfiguración
TeardownDesmontaje
TemplatePlantilla
TimeoutTiempo agotado
ArgumentsArgumentos

BDD prefixes

PrefixTranslation
GivenDado
WhenCuando
ThenEntonces
AndY
ButPero

Boolean strings

True/FalseValues
TrueVerdadero, Si, On
FalseFalso, No, Off, Ninguno

6.3.7   Finnish (fi)

Section headers

HeaderTranslation
SettingsAsetukset
VariablesMuuttujat
Test CasesTestit
TasksTehtävät
KeywordsAvainsanat
CommentsKommentit

Settings

SettingTranslation
LibraryKirjasto
ResourceResurssi
VariablesMuuttujat
NameNimi
DocumentationDokumentaatio
MetadataMetatiedot
Suite SetupSetin Alustus
Suite TeardownSetin Alasajo
Test SetupTestin Alustus
Task SetupTehtävän Alustus
Test TeardownTestin Alasajo
Task TeardownTehtävän Alasajo
Test TemplateTestin Malli
Task TemplateTehtävän Malli
Test TimeoutTestin Aikaraja
Task TimeoutTehtävän Aikaraja
Test TagsTestin Tagit
Task TagsTehtävän Tagit
Keyword TagsAvainsanan Tagit
TagsTagit
SetupAlustus
TeardownAlasajo
TemplateMalli
TimeoutAikaraja
ArgumentsArgumentit

BDD prefixes

PrefixTranslation
GivenOletetaan
WhenKun
ThenNiin
AndJa
ButMutta

Boolean strings

True/FalseValues
TrueTosi, Kyllä, Päällä
FalseEpätosi, Ei, Pois

6.3.8   French (fr)

Section headers

HeaderTranslation
SettingsParamètres
VariablesVariables
Test CasesUnités de test
TasksTâches
KeywordsMots-clés
CommentsCommentaires

Settings

SettingTranslation
LibraryBibliothèque
ResourceRessource
VariablesVariable
NameNom
DocumentationDocumentation
MetadataMéta-donnée
Suite SetupMise en place de suite
Suite TeardownDémontage de suite
Test SetupMise en place de test
Task SetupMise en place de tâche
Test TeardownDémontage de test
Task TeardownDémontage de test
Test TemplateModèle de test
Task TemplateModèle de tâche
Test TimeoutDélai de test
Task TimeoutDélai de tâche
Test TagsÉtiquette de test
Task TagsÉtiquette de tâche
Keyword TagsEtiquette de mot-clé
TagsÉtiquette
SetupMise en place
TeardownDémontage
TemplateModèle
TimeoutDélai d'attente
ArgumentsArguments

BDD prefixes

PrefixTranslation
GivenÉtant donné, Étant donné que, Étant donné qu', Soit, Sachant que, Sachant qu', Sachant, Etant donné, Etant donné que, Etant donné qu', Etant donnée, Etant données
WhenLorsque, Quand, Lorsqu'
ThenAlors, Donc
AndEt, Et que, Et qu'
ButMais, Mais que, Mais qu'

Boolean strings

True/FalseValues
TrueVrai, Oui, Actif
FalseFaux, Non, Désactivé, Aucun

6.3.9   Hindi (hi)

Section headers

HeaderTranslation
Settingsस्थापना
Variablesचर
Test Casesनियत कार्य प्रवेशिका
Tasksकार्य प्रवेशिका
Keywordsकुंजीशब्द
Commentsटिप्पणी

Settings

SettingTranslation
Libraryकोड़ प्रतिबिंब संग्रह
Resourceसंसाधन
Variablesचर
Name 
Documentationप्रलेखन
Metadataअधि-आंकड़ा
Suite Setupजांच की शुरुवात
Suite Teardownपरीक्षण कार्य अंत
Test Setupपरीक्षण कार्य प्रारंभ
Task Setupपरीक्षण कार्य प्रारंभ
Test Teardownपरीक्षण कार्य अंत
Task Teardownपरीक्षण कार्य अंत
Test Templateपरीक्षण ढांचा
Task Templateपरीक्षण ढांचा
Test Timeoutपरीक्षण कार्य समय समाप्त
Task Timeoutकार्य समयबाह्य
Test Tagsजाँचका उपनाम
Task Tagsकार्यका उपनाम
Keyword Tagsकुंजीशब्द का उपनाम
Tagsनिशान
Setupव्यवस्थापना
Teardownविमोचन
Templateसाँचा
Timeoutसमय समाप्त
Argumentsप्राचल

BDD prefixes

PrefixTranslation
Givenदिया हुआ
Whenजब
Thenतब
Andऔर
Butपरंतु

Boolean strings

True/FalseValues
Trueयथार्थ, निश्चित, हां, पर
Falseगलत, नहीं, हालाँकि, यद्यपि, नहीं, हैं

6.3.10   Italian (it)

Section headers

HeaderTranslation
SettingsImpostazioni
VariablesVariabili
Test CasesCasi Di Test
TasksAttività
KeywordsParole Chiave
CommentsCommenti

Settings

SettingTranslation
LibraryLibreria
ResourceRisorsa
VariablesVariabile
NameNome
DocumentationDocumentazione
MetadataMetadati
Suite SetupConfigurazione Suite
Suite TeardownDistruzione Suite
Test SetupConfigurazione Test
Task SetupConfigurazione Attività
Test TeardownDistruzione Test
Task TeardownDistruzione Attività
Test TemplateModello Test
Task TemplateModello Attività
Test TimeoutTimeout Test
Task TimeoutTimeout Attività
Test TagsTag Del Test
Task TagsTag Attività
Keyword TagsTag Parola Chiave
TagsTag
SetupConfigurazione
TeardownDistruzione
TemplateTemplate
TimeoutTimeout
ArgumentsParametri

BDD prefixes

PrefixTranslation
GivenDato
WhenQuando
ThenAllora
AndE
ButMa

Boolean strings

True/FalseValues
TrueVero, Sì, On
FalseFalso, No, Off, Nessuno

6.3.11   Japanese (ja)

New in Robot Framework 7.0.1.

Section headers

HeaderTranslation
Settings設定
Variables変数
Test Casesテスト ケース
Tasksタスク
Keywordsキーワード
Commentsコメント

Settings

SettingTranslation
Libraryライブラリ
Resourceリソース
Variables変数
Name名前
Documentationドキュメント
Metadataメタデータ
Suite Setupスイート セットアップ
Suite Teardownスイート ティアダウン
Test Setupテスト セットアップ
Task Setupタスク セットアップ
Test Teardownテスト ティアダウン
Task Teardownタスク ティアダウン
Test Templateテスト テンプレート
Task Templateタスク テンプレート
Test Timeoutテスト タイムアウト
Task Timeoutタスク タイムアウト
Test Tagsテスト タグ
Task Tagsタスク タグ
Keyword Tagsキーワード タグ
Tagsタグ
Setupセットアップ
Teardownティアダウン
Templateテンプレート
Timeoutタイムアウト
Arguments引数

BDD prefixes

PrefixTranslation
Given仮定, 指定, 前提条件
When条件, 次の場合, もし, 実行条件
Thenアクション, その時, 動作
Andおよび, 及び, かつ, 且つ, ならびに, 並びに, そして, それから
Butただし, 但し

Boolean strings

True/FalseValues
True真, 有効, はい, オン
False偽, 無効, いいえ, オフ

6.3.12   Korean (ko)

New in Robot Framework 7.1.

Section headers

HeaderTranslation
Settings설정
Variables변수
Test Cases테스트 사례
Tasks작업
Keywords키워드
Comments의견

Settings

SettingTranslation
Library라이브러리
Resource자료
Variables변수
Name이름
Documentation문서
Metadata메타데이터
Suite Setup스위트 설정
Suite Teardown스위트 중단
Test Setup테스트 설정
Task Setup작업 설정
Test Teardown테스트 중단
Task Teardown작업 중단
Test Template테스트 템플릿
Task Template작업 템플릿
Test Timeout테스트 시간 초과
Task Timeout작업 시간 초과
Test Tags테스트 태그
Task Tags작업 태그
Keyword Tags키워드 태그
Tags태그
Setup설정
Teardown중단
Template템플릿
Timeout시간 초과
Arguments주장

BDD prefixes

PrefixTranslation
Given주어진
When
Then보다
And그리고
But하지만

Boolean strings

True/FalseValues
True참, 네, 켜기
False거짓, 아니오, 끄기

6.3.13   Dutch (nl)

Section headers

HeaderTranslation
SettingsInstellingen
VariablesVariabelen
Test CasesTestgevallen
TasksTaken
KeywordsActiewoorden
CommentsOpmerkingen

Settings

SettingTranslation
LibraryBibliotheek
ResourceResource
VariablesVariabele
NameNaam
DocumentationDocumentatie
MetadataMetadata
Suite SetupSuitevoorbereiding
Suite TeardownSuite-afronding
Test SetupTestvoorbereiding
Task SetupTaakvoorbereiding
Test TeardownTestafronding
Task TeardownTaakafronding
Test TemplateTestsjabloon
Task TemplateTaaksjabloon
Test TimeoutTesttijdslimiet
Task TimeoutTaaktijdslimiet
Test TagsTestlabels
Task TagsTaaklabels
Keyword TagsActiewoordlabels
TagsLabels
SetupVoorbereiding
TeardownAfronding
TemplateSjabloon
TimeoutTijdslimiet
ArgumentsParameters

BDD prefixes

PrefixTranslation
GivenStel, Gegeven
WhenAls
ThenDan
AndEn
ButMaar

Boolean strings

True/FalseValues
TrueWaar, Ja, Aan
FalseOnwaar, Nee, Uit, Geen

6.3.14   Polish (pl)

Section headers

HeaderTranslation
SettingsUstawienia
VariablesZmienne
Test CasesPrzypadki Testowe
TasksZadania
KeywordsSłowa Kluczowe
CommentsKomentarze

Settings

SettingTranslation
LibraryBiblioteka
ResourceZasób
VariablesZmienne
NameNazwa
DocumentationDokumentacja
MetadataMetadane
Suite SetupInicjalizacja Zestawu
Suite TeardownUkończenie Zestawu
Test SetupInicjalizacja Testu
Task SetupInicjalizacja Zadania
Test TeardownUkończenie Testu
Task TeardownUkończenie Zadania
Test TemplateSzablon Testu
Task TemplateSzablon Zadania
Test TimeoutLimit Czasowy Testu
Task TimeoutLimit Czasowy Zadania
Test TagsZnaczniki Testu
Task TagsZnaczniki Zadania
Keyword TagsZnaczniki Słowa Kluczowego
TagsZnaczniki
SetupInicjalizacja
TeardownUkończenie
TemplateSzablon
TimeoutLimit Czasowy
ArgumentsArgumenty

BDD prefixes

PrefixTranslation
GivenZakładając, Zakładając, że, Mając
WhenJeżeli, Jeśli, Gdy, Kiedy
ThenWtedy
AndOraz, I
ButAle

Boolean strings

True/FalseValues
TruePrawda, Tak, Włączone
FalseFałsz, Nie, Wyłączone, Nic

6.3.15   Portuguese (pt)

Section headers

HeaderTranslation
SettingsDefinições
VariablesVariáveis
Test CasesCasos de Teste
TasksTarefas
KeywordsPalavras-Chave
CommentsComentários

Settings

SettingTranslation
LibraryBiblioteca
ResourceRecurso
VariablesVariável
NameNome
DocumentationDocumentação
MetadataMetadados
Suite SetupInicialização de Suíte
Suite TeardownFinalização de Suíte
Test SetupInicialização de Teste
Task SetupInicialização de Tarefa
Test TeardownFinalização de Teste
Task TeardownFinalização de Tarefa
Test TemplateModelo de Teste
Task TemplateModelo de Tarefa
Test TimeoutTempo Limite de Teste
Task TimeoutTempo Limite de Tarefa
Test TagsEtiquetas de Testes
Task TagsEtiquetas de Tarefas
Keyword TagsEtiquetas de Palavras-Chave
TagsEtiquetas
SetupInicialização
TeardownFinalização
TemplateModelo
TimeoutTempo Limite
ArgumentsArgumentos

BDD prefixes

PrefixTranslation
GivenDado
WhenQuando
ThenEntão
AndE
ButMas

Boolean strings

True/FalseValues
TrueVerdadeiro, Verdade, Sim, Ligado
FalseFalso, Não, Desligado, Desativado, Nada

6.3.16   Brazilian Portuguese (pt-BR)

Section headers

HeaderTranslation
SettingsConfigurações
VariablesVariáveis
Test CasesCasos de Teste
TasksTarefas
KeywordsPalavras-Chave
CommentsComentários

Settings

SettingTranslation
LibraryBiblioteca
ResourceRecurso
VariablesVariável
NameNome
DocumentationDocumentação
MetadataMetadados
Suite SetupConfiguração da Suíte
Suite TeardownFinalização de Suíte
Test SetupInicialização de Teste
Task SetupInicialização de Tarefa
Test TeardownFinalização de Teste
Task TeardownFinalização de Tarefa
Test TemplateModelo de Teste
Task TemplateModelo de Tarefa
Test TimeoutTempo Limite de Teste
Task TimeoutTempo Limite de Tarefa
Test TagsTest Tags
Task TagsTask Tags
Keyword TagsKeyword Tags
TagsEtiquetas
SetupInicialização
TeardownFinalização
TemplateModelo
TimeoutTempo Limite
ArgumentsArgumentos

BDD prefixes

PrefixTranslation
GivenDado
WhenQuando
ThenEntão
AndE
ButMas

Boolean strings

True/FalseValues
TrueVerdadeiro, Verdade, Sim, Ligado
FalseFalso, Não, Desligado, Desativado, Nada

6.3.17   Romanian (ro)

Section headers

HeaderTranslation
SettingsSetari
VariablesVariabile
Test CasesCazuri De Test
TasksSarcini
KeywordsCuvinte Cheie
CommentsComentarii

Settings

SettingTranslation
LibraryLibrarie
ResourceResursa
VariablesVariabila
NameNume
DocumentationDocumentatie
MetadataMetadate
Suite SetupConfigurare De Suita
Suite TeardownConfigurare De Intrerupere
Test SetupSetare De Test
Task SetupConfiguarare activitate
Test TeardownInrerupere De Test
Task TeardownIntrerupere activitate
Test TemplateSablon De Test
Task TemplateSablon de activitate
Test TimeoutTimp Expirare Test
Task TimeoutTimp de expirare activitate
Test TagsTaguri De Test
Task TagsEtichete activitate
Keyword TagsEtichete metode
TagsEtichete
SetupSetare
TeardownIntrerupere
TemplateSablon
TimeoutExpirare
ArgumentsArgumente

BDD prefixes

PrefixTranslation
GivenFie ca
WhenCand
ThenAtunci
AndSi
ButDar

Boolean strings

True/FalseValues
TrueAdevarat, Da, Cand
FalseFals, Nu, Oprit, Niciun

6.3.18   Russian (ru)

Section headers

HeaderTranslation
SettingsНастройки
VariablesПеременные
Test CasesЗаголовки тестов
TasksЗадача
KeywordsКлючевые слова
CommentsКомментарии

Settings

SettingTranslation
LibraryБиблиотека
ResourceРесурс
VariablesПеременные
Name 
DocumentationДокументация
MetadataМетаданные
Suite SetupИнициализация комплекта тестов
Suite TeardownЗавершение комплекта тестов
Test SetupИнициализация теста
Task SetupИнициализация задания
Test TeardownЗавершение теста
Task TeardownЗавершение задания
Test TemplateШаблон теста
Task TemplateШаблон задания
Test TimeoutЛимит выполнения теста
Task TimeoutЛимит задания
Test TagsТеги тестов
Task TagsМетки заданий
Keyword TagsМетки ключевых слов
TagsМетки
SetupИнициализация
TeardownЗавершение
TemplateШаблон
TimeoutЛимит
ArgumentsАргументы

BDD prefixes

PrefixTranslation
GivenДано
WhenКогда
ThenТогда
AndИ
ButНо

Boolean strings

True/FalseValues
True 
False 

6.3.19   Swedish (sv)

Section headers

HeaderTranslation
SettingsInställningar
VariablesVariabler
Test CasesTestfall
TasksTaskar
KeywordsNyckelord
CommentsKommentarer

Settings

SettingTranslation
LibraryBibliotek
ResourceResurs
VariablesVariabel
NameNamn
DocumentationDokumentation
MetadataMetadata
Suite SetupSvit konfigurering
Suite TeardownSvit nedrivning
Test SetupTest konfigurering
Task SetupTask konfigurering
Test TeardownTest nedrivning
Task TeardownTask nedrivning
Test TemplateTest mall
Task TemplateTask mall
Test TimeoutTest timeout
Task TimeoutTask timeout
Test TagsTest taggar
Task TagsArbetsuppgift taggar
Keyword TagsNyckelord taggar
TagsTaggar
SetupKonfigurering
TeardownNedrivning
TemplateMall
TimeoutTimeout
ArgumentsArgument

BDD prefixes

PrefixTranslation
GivenGivet
WhenNär
Then
AndOch
ButMen

Boolean strings

True/FalseValues
TrueSant, Ja, På
FalseFalskt, Nej, Av, Ingen

6.3.20   Thai (th)

Section headers

HeaderTranslation
Settingsการตั้งค่า
Variablesกำหนดตัวแปร
Test Casesการทดสอบ
Tasksงาน
Keywordsคำสั่งเพิ่มเติม
Commentsคำอธิบาย

Settings

SettingTranslation
Libraryชุดคำสั่งที่ใช้
Resourceไฟล์ที่ใช้
Variablesชุดตัวแปร
Name 
Documentationเอกสาร
Metadataรายละเอียดเพิ่มเติม
Suite Setupกำหนดค่าเริ่มต้นของชุดการทดสอบ
Suite Teardownคืนค่าของชุดการทดสอบ
Test Setupกำหนดค่าเริ่มต้นของการทดสอบ
Task Setupกำหนดค่าเริ่มต้นของงาน
Test Teardownคืนค่าของการทดสอบ
Task Teardownคืนค่าของงาน
Test Templateโครงสร้างของการทดสอบ
Task Templateโครงสร้างของงาน
Test Timeoutเวลารอของการทดสอบ
Task Timeoutเวลารอของงาน
Test Tagsกลุ่มของการทดสอบ
Task Tagsกลุ่มของงาน
Keyword Tagsกลุ่มของคำสั่งเพิ่มเติม
Tagsกลุ่ม
Setupกำหนดค่าเริ่มต้น
Teardownคืนค่า
Templateโครงสร้าง
Timeoutหมดเวลา
Argumentsค่าที่ส่งเข้ามา

BDD prefixes

PrefixTranslation
Givenกำหนดให้
Whenเมื่อ
Thenดังนั้น
Andและ
Butแต่

Boolean strings

True/FalseValues
True 
False 

6.3.21   Turkish (tr)

Section headers

HeaderTranslation
SettingsAyarlar
VariablesDeğişkenler
Test CasesTest Durumları
TasksGörevler
KeywordsAnahtar Kelimeler
CommentsYorumlar

Settings

SettingTranslation
LibraryKütüphane
ResourceKaynak
VariablesDeğişkenler
Name 
DocumentationDokümantasyon
MetadataÜstveri
Suite SetupTakım Kurulumu
Suite TeardownTakım Bitişi
Test SetupTest Kurulumu
Task SetupGörev Kurulumu
Test TeardownTest Bitişi
Task TeardownGörev Bitişi
Test TemplateTest Taslağı
Task TemplateGörev Taslağı
Test TimeoutTest Zaman Aşımı
Task TimeoutGörev Zaman Aşımı
Test TagsTest Etiketleri
Task TagsGörev Etiketleri
Keyword TagsAnahtar Kelime Etiketleri
TagsEtiketler
SetupKurulum
TeardownBitiş
TemplateTaslak
TimeoutZaman Aşımı
ArgumentsArgümanlar

BDD prefixes

PrefixTranslation
GivenDiyelim ki
WhenEğer ki
ThenO zaman
AndVe
ButAncak

Boolean strings

True/FalseValues
TrueDoğru, Evet, Açik
FalseYanliş, Hayir, Kapali

6.3.22   Ukrainian (uk)

Section headers

HeaderTranslation
SettingsНалаштування
VariablesЗмінні
Test CasesТест-кейси
TasksЗавдань
KeywordsКлючових слова
CommentsКоментарів

Settings

SettingTranslation
LibraryБібліотека
ResourceРесурс
VariablesЗмінна
Name 
DocumentationДокументація
MetadataМетадані
Suite SetupНалаштування Suite
Suite TeardownРозбірка Suite
Test SetupНалаштування тесту
Task SetupНалаштування завдання
Test TeardownРозбирання тестy
Task TeardownРозбір завдання
Test TemplateТестовий шаблон
Task TemplateШаблон завдання
Test TimeoutЧас тестування
Task TimeoutЧас очікування завдання
Test TagsТестові теги
Task TagsТеги завдань
Keyword TagsТеги ключових слів
TagsТеги
SetupВстановлення
TeardownCпростовувати пункт за пунктом
TemplateШаблон
TimeoutЧас вийшов
ArgumentsАргументи

BDD prefixes

PrefixTranslation
GivenДано
WhenКоли
ThenТоді
AndТа
ButАле

Boolean strings

True/FalseValues
True 
False 

6.3.23   Vietnamese (vi)

New in Robot Framework 6.1.

Section headers

HeaderTranslation
SettingsCài Đặt
VariablesCác biến số
Test CasesCác kịch bản kiểm thử
TasksCác nghiệm vụ
KeywordsCác từ khóa
CommentsCác chú thích

Settings

SettingTranslation
LibraryThư viện
ResourceTài nguyên
VariablesBiến số
NameTên
DocumentationTài liệu hướng dẫn
MetadataDữ liệu tham chiếu
Suite SetupTiền thiết lập bộ kịch bản kiểm thử
Suite TeardownHậu thiết lập bộ kịch bản kiểm thử
Test SetupTiền thiết lập kịch bản kiểm thử
Task SetupTiền thiểt lập nhiệm vụ
Test TeardownHậu thiết lập kịch bản kiểm thử
Task TeardownHậu thiết lập nhiệm vụ
Test TemplateMẫu kịch bản kiểm thử
Task TemplateMẫu nhiễm vụ
Test TimeoutThời gian chờ kịch bản kiểm thử
Task TimeoutThời gian chờ nhiệm vụ
Test TagsCác nhãn kịch bản kiểm thử
Task TagsCác nhãn nhiệm vụ
Keyword TagsCác từ khóa nhãn
TagsCác thẻ
SetupTiền thiết lập
TeardownHậu thiết lập
TemplateMẫu
TimeoutThời gian chờ
ArgumentsCác đối số

BDD prefixes

PrefixTranslation
GivenĐã cho
WhenKhi
ThenThì
And
ButNhưng

Boolean strings

True/FalseValues
TrueĐúng, Vâng, Mở
FalseSai, Không, Tắt, Không Có Gì

6.3.24   Chinese Simplified (zh-CN)

Section headers

HeaderTranslation
Settings设置
Variables变量
Test Cases用例
Tasks任务
Keywords关键字
Comments备注

Settings

SettingTranslation
Library程序库
Resource资源文件
Variables变量文件
Name 
Documentation说明
Metadata元数据
Suite Setup用例集启程
Suite Teardown用例集终程
Test Setup用例启程
Task Setup任务启程
Test Teardown用例终程
Task Teardown任务终程
Test Template用例模板
Task Template任务模板
Test Timeout用例超时
Task Timeout任务超时
Test Tags用例标签
Task Tags任务标签
Keyword Tags关键字标签
Tags标签
Setup启程
Teardown终程
Template模板
Timeout超时
Arguments参数

BDD prefixes

PrefixTranslation
Given假定
When
Then那么
And并且
But但是

Boolean strings

True/FalseValues
True真, 是, 开
False假, 否, 关, 空

6.3.25   Chinese Traditional (zh-TW)

Section headers

HeaderTranslation
Settings設置
Variables變量
Test Cases案例
Tasks任務
Keywords關鍵字
Comments備註

Settings

SettingTranslation
Library函式庫
Resource資源文件
Variables變量文件
Name 
Documentation說明
Metadata元數據
Suite Setup測試套啟程
Suite Teardown測試套終程
Test Setup測試啟程
Task Setup任務啟程
Test Teardown測試終程
Task Teardown任務終程
Test Template測試模板
Task Template任務模板
Test Timeout測試逾時
Task Timeout任務逾時
Test Tags測試標籤
Task Tags任務標籤
Keyword Tags關鍵字標籤
Tags標籤
Setup啟程
Teardown終程
Template模板
Timeout逾時
Arguments参数

BDD prefixes

PrefixTranslation
Given假定
When
Then那麼
And並且
But但是

Boolean strings

True/FalseValues
True真, 是, 開
False假, 否, 關, 空

6.4   Documentation formatting

It is possible to use simple HTML formatting withtest suite,test case anduser keyword documentation andfree suitemetadata in the test data, as well as whendocumenting testlibraries. The formatting is similar to the style used in mostwikis, and it is designed to be understandable both as plain text andafter the HTML transformation.

6.4.1   Handling whitespace in test data

Newlines

When documenting test suites, test cases and user keywords or adding metadatato test suites, newlines can be added manually using\nescape sequence.

*** Settings ***DocumentationFirst line.\n\nSecond paragraph. This time\nwith multiple lines.MetadataExample list- first item\n- second item\n- third

Note

As explained in theParagraphs section below, the single newline inSecond paragraph, this time\nwith multiple lines. does not actuallyaffect how that paragraph is rendered. Newlines are needed whencreatinglists or other such constructs, though.

Adding newlines manually to a long documentation takes some effort and extracharacters also make the documentation harder to read. This can be avoided,though, as newlines are inserted automaticallybetweencontinued documentation and metadata lines. In practice thismeans that the above example could be written also as follows.

*** Settings ***Documentation...First line.......Second paragraph. This time...with multiple lines.Metadata...Example list...- first item...- second item...- third

No automatic newline is added if a line already ends with a literal newlineor if it ends with anescaping backslash:

*** Test Cases ***Ends with newline    [Documentation]Ends with a newline and\n    ...automatic newline is not added.Ends with backslash    [Documentation]Ends with a backslash and \    ...no newline is added.

Spaces

Unlike elsewhere in Robot Framework data, leading spaces and consecutive internalspaces are preserved in documentation and metadata. This makes it possible, for example,to splitlist items to multiple rows and havepreformatted text with spaces:

*** Test Cases ***Long list item    [Documentation]    ...List:    ...- Short item.    ...- Second item is pretty long and it is split to    ...multiple rows. Leading spaces are preserved.    ...- Another short item.Preformatted text    [Documentation]    ...Example with consecutive internal spaces:    ...    ...| *** Test Cases ***    ...| Example    ...|Keyword

Note

Preserving spaces in documentation and metadata is new in Robot Framework 6.1.With earlier versions spaces need to be escaped with a backslash.

6.4.2   Paragraphs

All regular text in the formatted HTMLdocumentation is represented as paragraphs. In practice, lines separatedby a single newline will be combined in a paragraph regardless whether thenewline is added manually or automatically. Multiple paragraphs can be separatedwith an empty line (i.e. two newlines) and also tables, lists, and otherspecially formatted blocks discussed in subsequent sections end a paragraph.

For example, the following test suite or resource file documentation:

*** Settings ***Documentation...First paragraph has only one line.......Second paragraph, this time created...with multiple lines.

will be formatted in HTML as:

First paragraph has only one line.

Second paragraph, this time created with multiple lines.

6.4.3   Inline styles

The documentation syntax supports inline stylesbold,italic andcode.Bold text can be created by having an asterisk before and after theselected word or words, for example*this is bold*. Italicstyle works similarly, but the special character to use is anunderscore, for example,_italic_. It is also possible to havebold italic with the syntax_*bold italic*_.

The code style is created using double backticks like``code``.The result is monospaced text with light gray background.

Asterisks, underscores or double backticks alone, or in the middle of a word,do not start formatting, but punctuation characters before or after themare allowed. When multiple lines form aparagraph, all inline styles canspan over multiple lines.

Inline style examples
UnformattedFormatted
*bold*bold
_italic_italic
_*bold italic*_bold italic
``code``code
*bold*, then _italic_ and finally ``some code``bold, thenitalic and finallysome code
This is *bold\n
on multiple\n
lines*.
This isbold
on multiple
lines.

6.4.4   URLs

All strings that look like URLs are automatically converted intoclickable links. Additionally, URLs that end with extension.jpg,.jpeg,.png,.gif,.bmp or.svg (case-insensitive) will automatically create images. Forexample, URLs likehttp://example.com are turned into links, andhttp:///host/image.jpg andfile:///path/chart.pnginto images.

The automatic conversion of URLs to links is applied to all the datain logs and reports, but creating images is done only for test suite,test case and keyword documentation, and for test suite metadata.

Note

.svg image support is new in Robot Framework 3.2.

6.4.5   Custom links and images

It is possible to create custom linksand embed images using special syntax[link|content]. This createsa link or image depending arelink andcontent images.They are considered images if they have the same image extensions that arespecial withURLs or start withdata:image/. The surrounding squarebrackets and the pipe character between the parts are mandatory in all cases.

Note

Support for thedata:image/ prefix is new in Robot Framework 3.2.

Link with text content

If neitherlink norcontent is an image, the end result isa normal link wherelink is the link target andcontentthe visible text:

[file.html|this file] -> <a href="file.html">this file</a>[http://host|that host] -> <a href="http://host">that host</a>

Link with image content

Ifcontent is an image, you get a link where the link content is animage. Link target is created bylink and it can be either text or image:

[robot.html|robot.png] -> <a href="robot.html"><img src="robot.png"></a>[robot.html|data:image/png;base64,oooxxx=] -> <a href="robot.html"><img src="data:image/png;base64,oooxxx="></a>[image.jpg|thumb.jpg] -> <a href="image.jpg"><img src="thumb.jpg"></a>

Image with title text

Iflink is an image butcontent is not, the syntax creates animage where thecontent is the title text shown when mouse is overthe image:

[robot.jpeg|Robot rocks!] -> <img src="robot.jpeg" title="Robot rocks!">[data:image/png;base64,oooxxx=|Robot rocks!] -> <img src="data:image/png;base64,oooxxx=" title="Robot rocks!">

6.4.6   Section titles

If documentation gets longer, it is often a good idea to split it intosections. It is possible to separatesections with titles using syntax= My Title =, where the number ofequal signs denotes the level of the title:

= First section === Subsection ==Some text.== Second subsection ==More text.= Second section =You probably got the idea.

Notice that only three title levels are supported and that spaces betweenequal signs and the title text are mandatory.

6.4.7   Tables

Tables are created using pipe characters with spaces around themas column separators and newlines as row separators. Headercells can be created by surrounding the cell content with equal signsand optional spaces like= Header = or=Header=. Tablescells can also contain links and formatting such as bold and italic:

| =A= |  =B=  | = C =  || _1_ | Hello | world! || _2_ | Hi    |

The created table always has a thin border and normal text is left-aligned.Text in header cells is bold and centered. Empty cells are automaticallyadded to make rows equally long. For example, the above example would beformatted like this in HTML:

ABC
1Helloworld
2Hi

6.4.8   Lists

Lists are created by starting a line with a hyphen and space ('- '). List itemscan be split into multiple lines by indenting continuing lines with one or morespaces. A line that does not start with '- ' and is not indented ends the list:

Example:- a list item- second list item  is continuedThis is outside the list.

The above documentation is formatted like this in HTML:

Example:

  • a list item
  • second list item is continued

This is outside the list.

6.4.9   Preformatted text

It is possible to embed blocks ofpreformatted text in the documentation. Preformatted block is created bystarting lines with '| ', one space being mandatory after the pipe characterexcept on otherwise empty lines. The starting '| ' sequence will be removedfrom the resulting HTML, but all other whitespace is preserved.

In the following documentation, the two middle lines form a preformattedblock when converted to HTML:

Doc before block:| inside block|    some   additional whitespaceAfter block.

The above documentation is formatted like this:

Doc before block:

inside block  some   additional whitespace

After block.

6.4.10   Horizontal ruler

Horizontal rulers (the<hr> tag) make it possible to separate largersections from each others, and they can be created by having three or morehyphens alone on a line:

Some text here.---More text...

The above documentation is formatted like this:

Some text here.


More text...

6.5   Time format

Robot Framework has its own time format that is both flexible to use and easyto understand. It is used by several keywords (for example,BuiltIn keywordsSleep andWait Until Keyword Succeeds),DateTime library, andtimeouts.

6.5.1   Time as number

The time can always be given as a plain number, in which case it isinterpreted to be seconds. Both integers and floating point numberswork, and it is possible to use either real numbers or stringscontaining numerical values.

Note

In some contexts plain numbers can be interpreted otherwise astimes. For example, withWHILE loop limit integers denotethe maximum iteration count.

6.5.2   Time as time string

Representing the time as a time string means using a format such as2 minutes 42 seconds, which is normally easier to understand thanjust having the value as seconds. It is, for example, not so easy tounderstand how long a time4200 is in seconds, but1 hour 10 minutes is clear immediately.

The basic idea of this format is having first a number and then a textspecifying what time that number represents. Numbers can be eitherintegers or floating point numbers, the whole format is case and spaceinsensitive, and it is possible to add- prefix to specify negativetimes. The available time specifiers are:

  • weeks, week, w
  • days, day, d
  • hours, hour, h
  • minutes, minute, mins, min, m
  • seconds, second, secs, sec, s
  • milliseconds, millisecond, millis, ms
  • microseconds, microsecond, us, μs
  • nanoseconds, nanosecond, ns

Examples:

1 min 30 secs1.5 minutes90 s1 day 2 hours 3 minutes 4 seconds 5 milliseconds 6 microseconds 7 nanoseconds8 weeks 7 days 6 hours 5 minutes 4 seconds 3 milliseconds 2 microseconds 1 nanosecond1d 2h 3m 4s 5ms 6μs 7 ns8w 7d 6h 5m 4s 3ms 2μs 1ns- 10 seconds

Note

Support for micro and nanoseconds is new in Robot Framework 6.0.Support for weeks is new in Robot Framework 7.1.

6.5.3   Time as "timer" string

Time can also be given in timer likeformathh:mm:ss.mil. In this format both hour and millisecond partsare optional, leading and trailing zeros can be left out when they are notmeaningful, and negative times can be represented by adding the-prefix. For example, following timer and time string values are identical:

Timer and time string examples
TimerTime string
00:00:011 second
01:02:031 hour 2 minutes 3 seconds
1:00:001 hour
100:00:00100 hours
00:022 seconds
42:0042 minutes
00:01:02.0031 minute 2 seconds 3 milliseconds
00:01.51.5 seconds
-01:02.345- 1 minute 2 seconds 345 milliseconds

6.6   Boolean arguments

Many keywords in Robot Frameworkstandard libraries accept arguments thatare handled as Boolean values true or false. If such an argument is given asa string, it is considered false if it is an empty string or equal toFALSE,NONE,NO,OFF or0, case-insensitively. Otherstrings are considered true unless the keyword documentation explicitlystates otherwise, and other argument types are tested using the samerules as in Python.

*** Keywords ***True examplesShould Be Equal    ${x}    ${y}Custom errorvalues=True# Strings are generally true.Should Be Equal    ${x}    ${y}Custom errorvalues=yes# Same as the above.Should Be Equal    ${x}    ${y}Custom errorvalues=${TRUE}# Python `True` is true.Should Be Equal    ${x}    ${y}Custom errorvalues=${42}# Numbers other than 0 are true.False examplesShould Be Equal    ${x}    ${y}Custom errorvalues=False# String `false` is false.Should Be Equal    ${x}    ${y}Custom errorvalues=no# Also string `no` is false.Should Be Equal    ${x}    ${y}Custom errorvalues=${EMPTY}# Empty string is false.Should Be Equal    ${x}    ${y}Custom errorvalues=${FALSE}# Python `False` is false.Should Be Equal    ${x}    ${y}Custom errorvalues=no values# Special false string with this keyword.

Note

ConsideringOFF and0 false is new in Robot Framework 3.1.

6.7   Evaluating expressions

This appendix explains how expressions are evaluated using Python in differentcontexts and how variables in expressions are handled.

6.7.1   Introduction

Constructs such asIF/ELSE structures,WHILE loops andinline Python evaluationas well as severalBuiltIn keywords accept an expression that is evaluated in Python:

*** Test Cases ***IF/ELSEIF    ${x} > 0Log to console   ${x} is positiveELSELog to console   ${x} is negativeENDInline Python evaluationLog to console    ${x} is${{'positive' if${x} > 0 else 'negative'}}Evaluate keyword    ${type} =Evaluate'positive' if${x} > 0 else 'negative'Log to console    ${x} is${type}Should Be True keywordShould Be True    ${x} > 0

Notice that instead of creating complicatedexpressions, it is often better to move the logic into atest library.That typically eases maintenance and also enhances execution speed.

6.7.2   Evaluation namespace

Expressions are evaluated using Python'seval function so that normal Pythonconstructs like'${x}' == 'expected',${x} > 0 and'${x}'.upper() not in ('FAIL', 'BAD') can be used and allbuiltin functions likelen() andint() are available.In addition to that, all unrecognized Python variables are considered to bemodules that are automatically imported. It is possible to use all availablePython modules, including the standard modules and the installed third partymodules.

The following examples demonstrate using Python builtins as well as modulesusing theinline Python evaluation syntax, but same expressions would alsowork withIF/ELSE structures andBuiltIn keywords without the need to usethe${{}} decoration around the expression:

*** Variables ***${VAR}123*** Test Cases ***Python syntaxShould Be True       ${{'${VAR}' == '123'}}Should Be True       ${{'${VAR}'.startswith('x') or '${VAR}' in '012345'}}Python builtinsShould Be Equal      ${{len('${VAR}')}}        ${3}Should Be Equal      ${{int('${VAR}')}}        ${123}Access modulesShould Be Equal      ${{os.sep}}               ${/}Should Be Equal      ${{round(math.pi, 2)}}    ${3.14}Should Start With    ${{robot.__version__}}4.

A limitation of using modules is that nested modules likerootmod.submodcan only be used if the root module automatically imports the submodule. That isnot always the case and using such modules is not possible. An concrete examplethat is relevant in the automation context is theselenium module that isimplemented, at least at the time of this writing, so that just importingselenium does not import theselenium.webdriver submodule.Another limitation is that modules cannot be used in the expression part ofa list comprehension when using Python 3. A workaround to both of these problemsis using theBuiltIn keywordEvaluate that accepts modules to be importedand added to the evaluation namespace as an argument:

*** Test Cases ***Does not work due to nested module structureLog    ${{selenium.webdriver.ChromeOptions()}}Evaluate keyword with nested module    ${options} =Evaluateselenium.webdriver.ChromeOptions()modules=selenium.webdriverLog    ${options}Does not work due to list comprehensionLog    ${{[json.loads(item) for item in ('1', '"b"')]}}Evaluate keyword with list comprehension    ${items} =Evaluate[json.loads(item) for item in ('1', '"b"')]modules=jsonLog    ${items}

TheEvaluate keyword also supports custom evaluation namespaces if furthercustomization is needed. See its documentation in theBuiltIn library for more details.

6.7.3   Using variables

Normal${variable} syntax

When a variable is used in the expression using the normal${variable}syntax, its value is replaced before the expression is evaluated. Thismeans that the value used in the expression will be the stringrepresentation of the variable value, not the variable value itself.This is not a problem with numbers and other objects that have a stringrepresentation that can be evaluated directly. For example, if we havea return code as an integer in variable${rc}, using something like${rc} > 0 is fine.

With other objects the behavior depends on the string representation.Most importantly, strings must always be quoted either withsingle or double quotes like'${x}', and if they can contain newlines, they must betriple-quoted like'''${x}'''. Strings containing quotes themselves causeadditional problems, but triple-quoting typically handles them. Also thebackslash character\ is problematic, but can be handled byusing Python's raw-string notation liker'${path}'.

*** Test Cases ***Using normal variable syntaxShould Be True    ${rc} > 0IF'${status}'.upper() == 'PASS'LogPassedENDIF'FAIL' in r'''${output}'''LogOutput contains FAILEND

Special$variable syntax

Quoting strings is not that convenient, but there are cases where replacing the variablewith its string representation causes even bigger problems. For example, if the variablevalue can be either a string or PythonNone, quoting like'${var}' is needed becauseotherwise strings do not work, but thenNone is interpreted to be a string as well.Luckily there is an easy solution to these problems discussed in this section.

Actual variables values are available in the evaluation namespace and can be accessedusing special variable syntax without the curly braces like$variable. Such variablesshould never be quoted, not even if they contain strings.

Compare this these examples with the example in the previous section:

*** Test Cases ***Using special variable syntaxShould Be True$rc > 0IF$status.upper() == 'PASS'LogPassedENDIF'FAIL' in $outputLogOutput contains FAILENDOnly possible using special variable syntaxShould Be True$example is not NoneShould Be Truelen($result) > 1 and $result[1] == 'OK'

Using the$variable syntax slows down expression evaluation a little.This should not typically matter, but should be taken into account ifcomplex expressions are evaluated often and there are strict timeconstrains. Moving such logic to test libraries is typically a good ideaanyway.

Note

Due to technical reasons, these special variables are available duringevaluation as local variables. That makes them unavailable in non-localscopes such as in the expression part of list comprehensions and insidelambdas.

6.8   Registrations

This appendix lists file extensions, media types, and so on, that areassociated with Robot Framework.

6.8.1   Suite file extensions

Suite files with the following extensions are parsed automatically:

.robot
Suite file using theplain text format.
.robot.rst
Suite file using thereStructuredText format.
.rbt
Suite file using theJSON format.

Using other extensions is possible, but it requiresseparate configuration.

6.8.2   Resource file extensions

Resource files can use the following extensions:

.resource
Recommended when using the plain text format.
.robot,.txt and.tsv
Supported with the plain text format for backwards compatibility reasons..resource is recommended and may be mandated in the future.
.rst and.rest
Resource file using thereStructuredText format.
.rsrc and.json
Resource file using theJSON format.

6.8.3   Media type

The media type to use with Robot Framework data istext/robotframework.

6.8.4   Remote server port

The defaultremote server port is 8270. The port has beenregistered by IANA.


Generated byreStructuredText. Syntax highlighting byPygments.

[8]ページ先頭

©2009-2025 Movatter.jp