A parallel executor for Robot Framework tests. With Pabot you can split one execution into multiple and save test execution time.
- Installation
- Basic use
- Contact
- Contributing
- Command-line options
- PabotLib
- Controlling execution order
- Programmatic use
- Global variables
- Output Files Generated by Pabot
- Artifacts Handling and Parallel Execution Notes
From PyPi:
pip install -U robotframework-pabot
OR clone this repository and run:
setup.py install
OR clone this repository and run:
pip install --editable .
Split execution to suite files.
pabot [path to tests]
Split execution on test level.
pabot --testlevelsplit [path to tests]
Run same tests with two different configurations.
pabot --argumentfile1 first.args --argumentfile2 second.args [path to tests]
For more complex cases please read onward.
Join Pabot Slack channel in Robot Framework slack. Get invite to Robot Framework slack.
There are several ways you can help in improving this tool:
- Report an issue or an improvement idea to the issue tracker
- Contribute by programming and making a pull request (easiest way is to work on an issue from the issue tracker)
pabot [--verbose|--testlevelsplit|--command .. --end-command|
--processes num|--no-pabotlib|--pabotlibhost host|--pabotlibport port|
--processtimeout num|
--shard i/n|
--artifacts extensions|--artifactsinsubfolders|
--resourcefile file|--argumentfile[num] file|--suitesfrom file|--ordering file|
--chunk|
--pabotprerunmodifier modifier|
--no-rebot|
--help|--version]
[robot options] [path ...]
PabotLib remote server is started by default to enable locking and resource distribution between parallel test executions.
Supports all Robot Framework command line options and also following pabot options:
--verbose
More output from the parallel execution.
--testlevelsplit
Split execution on test level instead of default suite level. If .pabotsuitenames contains both tests and suites then
this will only affect new suites and split only them. Leaving this flag out when both suites and tests in
.pabotsuitenames file will also only affect new suites and add them as suite files.
--command [ACTUAL COMMANDS TO START ROBOT EXECUTOR] --end-command
RF script for situations where robot is not used directly.
--processes [NUMBER OF PROCESSES]
How many parallel executors to use (default max of 2 and cpu count). Special option "all" will use as many processes as
there are executable suites or tests.
--no-pabotlib
Disable the PabotLib remote server if you don't need locking or resource distribution features.
--pabotlibhost [HOSTNAME]
Connect to an already running instance of the PabotLib remote server at the given host (disables the local PabotLib
server start). For example, to connect to a remote PabotLib server running on another machine:
pabot --pabotlibhost 192.168.1.123 --pabotlibport 8271 tests/
The remote server can also be started and executed separately from pabot instances:
python -m pabot.pabotlib <path_to_resourcefile> <host> <port>
python -m pabot.pabotlib resource.txt 192.168.1.123 8271
This enables sharing a resource with multiple Robot Framework instances.
Additional details:
- The default value for --pabotlibhost is 127.0.0.1.
- If you provide a hostname other than 127.0.0.1, the local PabotLib server startup is automatically disabled.
--pabotlibport [PORT]
Port number of the PabotLib remote server (default is 8270). See --pabotlibhost for more information.
Behavior with port and host settings:
- If you set the port value to 0 and --pabotlibhost is 127.0.0.1 (default), a free port on localhost will be assigned automatically.
--processtimeout [TIMEOUT]
Maximum time in seconds to wait for a process before killing it. If not set, there's no timeout.
--shard [INDEX]/[TOTAL]
Optionally split execution into smaller pieces. This can be used for distributing testing to multiple machines.
--artifacts [FILE EXTENSIONS]
List of file extensions (comma separated). Defines which files (screenshots, videos etc.) from separate reporting
directories would be copied and included in a final report. Possible links to copied files in RF log would be updated
(only relative paths supported). The default value is png
.
Examples:
--artifacts png,mp4,txt
The artifact naming conventions are described in the README.md section: Output Files Generated by Pabot.
--artifactsinsubfolders
Copy artifacts located not only directly in the RF output dir, but also in it's sub-folders.
--resourcefile [FILEPATH]
Indicator for a file that can contain shared variables for distributing resources. This needs to be used together with
pabotlib option. Resource file syntax is same as Windows ini files. Where a section is a shared set of variables.
--argumentfile[INTEGER] [FILEPATH]
Run same suites with multiple argumentfile options.
For example:
--argumentfile1 arg1.txt --argumentfile2 arg2.txt
--suitesfrom [FILEPATH TO OUTPUTXML]
Optionally read suites from output.xml file. Failed suites will run first and longer running ones will be executed
before shorter ones.
--ordering [FILE PATH]
Optionally give execution order from a file.
--chunk
Optionally chunk tests to PROCESSES number of robot runs. This can save time because all the suites will share the same
setups and teardowns.
--pabotprerunmodifier [PRERUNMODIFIER MODULE OR CLASS]
Like Robot Framework's --prerunmodifier, but executed only once in the pabot's main process after all other
--prerunmodifiers. But unlike the regular --prerunmodifier command, --pabotprerunmodifier is not executed again in each
pabot subprocesses. Depending on the intended use, this may be desirable as well as more efficient. Can be used, for
example, to modify the list of tests to be performed.
--no-rebot
If specified, the tests will execute as usual, but Rebot will not be called to merge the logs. This option is designed
for scenarios where Rebot should be run later due to large log files, ensuring better memory and resource availability.
Subprocess results are stored in the pabot_results folder.
--help
Print usage instructions.
--version
Print version information.
Example usages:
pabot test_directory
pabot --exclude FOO directory_to_tests
pabot --command java -jar robotframework.jar --end-command --include SMOKE tests
pabot --processes 10 tests
pabot --pabotlibhost 192.168.1.123 --pabotlibport 8271 --processes 10 tests
pabot --artifacts png,mp4,txt --artifactsinsubfolders directory_to_tests
# To disable PabotLib:
pabot --no-pabotlib tests
pabot.PabotLib provides keywords that will help communication and data sharing between the executor processes. These can be helpful when you must ensure that only one of the processes uses some piece of data or operates on some part of the system under test at a time.
PabotLib Docs are located at https://pabot.org/PabotLib.html.
test.robot
*** Settings ***
Library pabot.PabotLib
*** Test Case ***
Testing PabotLib
Acquire Lock MyLock
Log This part is critical section
Release Lock MyLock
${valuesetname}= Acquire Value Set admin-server
${host}= Get Value From Set host
${username}= Get Value From Set username
${password}= Get Value From Set password
Log Do something with the values (for example access host with username and password)
Release Value Set
Log After value set release others can obtain the variable values
valueset.dat
[Server1]
tags=admin-server
HOST=123.123.123.123
USERNAME=user1
PASSWORD=password1
[Server2]
tags=server
HOST=121.121.121.121
USERNAME=user2
PASSWORD=password2
[Server3]
tags=admin-server
HOST=222.222.222.222
USERNAME=user3
PASSWORD=password4
pabot call using resources from valueset.dat
pabot --pabotlib --resourcefile valueset.dat test.robot
.pabotsuitenames file contains the list of suites that will be executed.
File is created during pabot execution if not already there.
The file is a cache that pabot uses when re-executing same tests to speed up processing.
This file can be partially manually edited but easier option is to use --ordering FILENAME
.
First 4 rows contain information that should not be edited - pabot will edit these when something changes.
After this come the suite names.
With --ordering FILENAME
you can have a list that controls order also. The syntax is same as .pabotsuitenames file syntax but does not contain 4 hash rows that are present in .pabotsuitenames.
Note: The --ordering
file is intended only for defining the execution order of suites and tests. The actual selection of what to run must still be done using options like --test
, --suite
, --include
, or --exclude
.
There different possibilities to influence the execution:
- The order of suites can be changed.
- If a directory (or a directory structure) should be executed sequentially, add the directory suite name to a row as a
--suite
option. This usage is also supported when--testlevelsplit
is enabled. As an alternative to using--suite
options, you can also group tests into sequential batches using{}
braces. (See below for details.) Note that if multiple--suite
options are used, they must not reference the same test case. This means you cannot specify both parent and child suite names at the same time. For instance:
--suite Top Suite.Sub Suite
--suite Top Suite
- If the base suite name is changing with robot option
--name / -N
you can use either the new or old full test path. For example:
--test New Suite Name.Sub Suite.Test 1
OR
--test Old Suite Name.Sub Suite.Test 1
- You can add a line with text
#WAIT
to force executor to wait until all previous suites have been executed. - You can group suites and tests together to same executor process by adding line
{
before the group and}
after. Note that#WAIT
cannot be used inside a group. - You can introduce dependencies using the word
#DEPENDS
after a test declaration. This keyword can be used several times if it is necessary to refer to several different tests. The ordering algorithm is designed to preserve the exact user-defined order as closely as possible. However, if a test's execution dependencies are not yet satisfied, the test is postponed and moved to the earliest possible stage where all its dependencies are fulfilled. Please take care that in case of circular dependencies an exception will be thrown. Note that each#WAIT
splits suites into separate execution blocks, and it's not possible to define dependencies for suites or tests that are inside another#WAIT
block or inside another{}
braces. - Note: Within a group
{}
, neither execution order nor the#DEPENDS
keyword currently works. This is due to limitations in Robot Framework, which is invoked within Pabot subprocesses. These limitations may be addressed in a future release of Robot Framework. For now, tests or suites within a group will be executed in the order Robot Framework discovers them — typically in alphabetical order. - An example could be:
--test robotTest.1 Scalar.Test With Environment Variables #DEPENDS robotTest.1 Scalar.Test with BuiltIn Variables of Robot Framework
--test robotTest.1 Scalar.Test with BuiltIn Variables of Robot Framework
--test robotTest.2 Lists.Test with Keywords and a list
#WAIT
--test robotTest.2 Lists.Test with a Keyword that accepts multiple arguments
{
--test robotTest.2 Lists.Test with some Collections keywords
--test robotTest.2 Lists.Test to access list entries
}
--test robotTest.3 Dictionary.Test that accesses Dictionaries
--test robotTest.3 Dictionary.Dictionaries for named arguments #DEPENDS robotTest.3 Dictionary.Test that accesses Dictionaries
--test robotTest.1 Scalar.Test Case With Variables #DEPENDS robotTest.3 Dictionary.Test that accesses Dictionaries
--test robotTest.1 Scalar.Test with Numbers #DEPENDS robotTest.1 Scalar.Test With Arguments and Return Values
--test robotTest.1 Scalar.Test Case with Return Values #DEPENDS robotTest.1 Scalar.Test with Numbers
--test robotTest.1 Scalar.Test With Arguments and Return Values
--test robotTest.3 Dictionary.Test with Dictionaries as Arguments
--test robotTest.3 Dictionary.Test with FOR loops and Dictionaries #DEPENDS robotTest.1 Scalar.Test Case with Return Values
- By using the command
#SLEEP X
, whereX
is an integer in the range [0-3600] (in seconds), you can define a startup delay for each subprocess.#SLEEP
affects the next line unless the next line starts a group with{
, in which case the delay applies to the entire group. If the next line begins with--test
or--suite
, the delay is applied to that specific item. Any other occurrences of#SLEEP
are ignored. Note that#SLEEP
has no effect within a group, i.e., inside a subprocess.
The following example clarifies the behavior:
pabot --processes 2 --ordering order.txt data_1
where order.txt is:
#SLEEP 1
{
#SLEEP 2
--suite Data 1.suite A
#SLEEP 3
--suite Data 1.suite B
#SLEEP 4
}
#SLEEP 5
#SLEEP 6
--suite Data 1.suite C
#SLEEP 7
--suite Data 1.suite D
#SLEEP 8
prints something like this:
2025-02-15 19:15:00.408321 [0] [ID:1] SLEEPING 6 SECONDS BEFORE STARTING Data 1.suite C
2025-02-15 19:15:00.408321 [1] [ID:0] SLEEPING 1 SECONDS BEFORE STARTING Group_Data 1.suite A_Data 1.suite B
2025-02-15 19:15:01.409389 [PID:52008] [1] [ID:0] EXECUTING Group_Data 1.suite A_Data 1.suite B
2025-02-15 19:15:06.409024 [PID:1528] [0] [ID:1] EXECUTING Data 1.suite C
2025-02-15 19:15:09.257564 [PID:52008] [1] [ID:0] PASSED Group_Data 1.suite A_Data 1.suite B in 7.8 seconds
2025-02-15 19:15:09.259067 [1] [ID:2] SLEEPING 7 SECONDS BEFORE STARTING Data 1.suite D
2025-02-15 19:15:09.647342 [PID:1528] [0] [ID:1] PASSED Data 1.suite C in 3.2 seconds
2025-02-15 19:15:16.260432 [PID:48156] [1] [ID:2] EXECUTING Data 1.suite D
2025-02-15 19:15:18.696420 [PID:48156] [1] [ID:2] PASSED Data 1.suite D in 2.4 seconds
Library offers an endpoint main_program
that will not call sys.exit
. This can help in developing your own python program around pabot.
import sys
from pabot.pabot import main_program
def amazing_new_program():
print("Before calling pabot")
exit_code = main_program(['tests'])
print(f"After calling pabot (return code {exit_code})")
sys.exit(exit_code)
Pabot will insert following global variables to Robot Framework namespace. These are here to enable PabotLib functionality and for custom listeners etc. to get some information on the overall execution of pabot.
PABOTQUEUEINDEX - this contains a unique index number for the execution. Indexes start from 0.
PABOTLIBURI - this contains the URI for the running PabotLib server
PABOTEXECUTIONPOOLID - this contains the pool id (an integer) for the current Robot Framework executor. This is helpful for example when visualizing the execution flow from your own listener.
PABOTNUMBEROFPROCESSES - max number of concurrent processes that pabot may use in execution.
CALLER_ID - a universally unique identifier for this execution.
Pabot generates several output files and folders during execution, both for internal use and for analysis purposes.
Pabot creates a .pabotsuitenames
file in the working directory. This is an internal hash file used to speed up execution in certain scenarios.
This file can also be used as a base for the --ordering
file as described earlier. Although technically it can be modified, it will be overwritten during the next execution.
Therefore, it is recommended to maintain a separate file for the --ordering
option if needed.
In addition to the standard log.html
, report.html
, and output.xml
files, the specified --outputdir
will contain:
- A folder named
pabot_results
, and - All defined artifacts (default:
.png
files) - Optionally, artifacts from subfolders if
--artifactsinsubfolders
is used
Artifacts are copied into the output directory and renamed with the following structure:
TIMESTAMP-ARGUMENT_INDEX-PABOTQUEUEINDEX
If you use the special option notimestamps
at the end of the --artifacts
command, (For example: --artifacts png,txt,notimestamps
) the timestamp part will be omitted, and the name will be in the format:
ARGUMENT_INDEX-PABOTQUEUEINDEX
- TIMESTAMP = Time of
pabot
command invocation (not the screenshot's actual timestamp), format:YYYYmmdd_HHMMSS
- ARGUMENT_INDEX = Optional index number, only used if
--argumentfileN
options are given - PABOTQUEUEINDEX = Process queue index (see section Global Variables)
The structure of the pabot_results
folder is as follows:
pabot_results/
├── [N]/ # Optional: N = argument file index (if --argumentfileN is used)
│ └── PABOTQUEUEINDEX/ # One per subprocess
│ ├── output.xml
│ ├── robot_argfile.txt
│ ├── robot_stdout.out
│ ├── robot_stderr.out
│ └── artifacts...
Each PABOTQUEUEINDEX
folder contains as default:
robot_argfile.txt
– Arguments used in that subprocessrobot_stdout.out
androbot_stderr.out
– Stdout and stderr of the subprocessoutput.xml
– The partial output file to be merged later- Artifacts – Screenshots or other files copied from subprocess folders
Note: The entire
pabot_results
folder is considered temporary and will be deleted/overwritten on the nextpabot
run using the same--outputdir
.
Due to parallel execution, artifacts like screenshots should ideally be:
- Embedded directly into the XML using tools like SeleniumLibrary with the
EMBED
option
Example:
Library SeleniumLibrary screenshot_root_directory=EMBED
- Or saved to the subprocess’s working directory (usually default behavior), ensuring separation across processes
If you manually specify a shared screenshot directory in your test code, all processes will write to it concurrently, which may cause issues such as overwriting or missing files if screenshots are taken simultaneously.