Browse the Knowledge Hub211 resources
Robot Framework review: tutorial, pros and cons
Robot Framework is an open-source, keyword-driven automation framework written in Python, used for acceptance testing and robotic process automation. Tests are tables of readable keywords, and capability comes from libraries such as Browser, SeleniumLibrary, RequestsLibrary and AppiumLibrary. Version 7.5, released on 14 September 2026, adds test metadata, custom console loggers and tests embedded in Markdown files.
QAble runs this tool on client engagements. The assessment below is from that experience.
- last reviewed
- 13 October 2026
- version covered
- Robot Framework 7.5
- licence
- Open source
At a glance
Robot Framework at a glance
- Vendor
- Robot Framework Foundation
- Category
- Web automation, API testing, Mobile automation, Desktop automation
- Licence
- Open source (Apache 2.0)
- Platforms
- Cross-platform
- Languages
- Robot Framework syntax, Python
- Integrates with
- SeleniumLibrary, Browser library, Appium, Pabot, Jenkins
- First released
- 2008
- Version reviewed
- Robot Framework 7.5
Verdict
Our verdict on Robot Framework
Strengths
- Tests read as keyword tables, so testers and business reviewers can follow them and often write them
- One syntax and one report across web, API, mobile, desktop and RPA, through separate libraries
- log.html and report.html after every run show each keyword, argument, timing and failure screenshot
- Any Python function becomes a keyword, so complex logic moves into ordinary, testable code
- Browser library brings Playwright’s auto-waiting and strict selectors to Robot tests
- Free under Apache 2.0, with an optional foundation membership that funds maintenance
Weaknesses
- No built-in parallelism; Pabot is a separate tool and needs independent suites
- Whitespace-separated syntax is unfamiliar to programmers and easy to break with a single space
- Logic-heavy tests become verbose; loops and conditions belong in Python libraries
- Readability depends on a keyword layer someone must design, and suites decay quickly without one
Best for
Mixed-skill teams where testers, analysts or business users need to read and sometimes write tests, and organisations that want one syntax, one runner and one report across web, API, mobile, desktop and RPA work. The log and report files written after every run are excellent with no configuration, and people who never open the code can read them. It also suits Python shops, because any Python function becomes a keyword with no glue code.
Not for
Engineer-heavy teams who would rather write tests as code, where pytest or Playwright Test is more direct and less ceremonious. It is also a poor fit for logic-heavy tests: loops, branching and data manipulation in Robot syntax are verbose and belong in a Python library instead. And teams that want fast, fine-grained developer feedback inside an IDE will find a code-first runner integrates more naturally with their tools.
Setup cost
Low to start: pip install robotframework and a library, and a first test runs in minutes. Browser library adds a Node.js dependency, or its bundled batteries package, plus rfbrowser init to download Playwright’s browsers. The significant cost is the keyword layer. Someone capable has to design resource files, naming and abstraction levels before the readability benefit is real; without that investment, a Robot suite is just browser calls in a different syntax.
Maintenance burden
Depends almost entirely on whether that keyword layer exists. With deliberate levels, business keywords calling page keywords calling library keywords, a redesign touches one resource file. Without it, every test is a flat list of clicks with raw selectors and a redesign breaks all of them at once. Libraries move at their own pace: Browser library releases every few weeks and needs rfbrowser clean-node and init after each upgrade, so pin versions in requirements.txt and upgrade them together.
Honest limitations
No native parallel execution: Pabot provides it, splitting by suite by default, and requires suites to be genuinely independent first. The space-separated syntax, where two or more spaces divide cells, trips up programmers and makes some mistakes invisible. Abstraction can hide so much that a readable test gives no hint of what it actually does. Debugging and refactoring support are weaker than for plain Python, and the framework is only as good as its libraries, which separate projects maintain.
How it works
How Robot Framework works
Tables of keywords, run top to bottom
A Robot Framework file is a set of sections: Settings, Variables, Test Cases or Tasks, and Keywords. Each row in a test starts with a keyword name followed by its arguments, with cells separated by two or more spaces or by pipes. Keywords come from two places. User keywords are written in Robot syntax from other keywords, and live in the same file or in resource files shared across suites. Library keywords are implemented in code. Running robot on a directory turns the folder tree into a suite tree, and setups and teardowns at suite and test level wrap the steps, which is how browsers are opened once per suite and pages once per test.
Libraries do the real work
A library is usually a Python module or class, and each public function or method becomes a keyword: fill_text becomes Fill Text. Arguments arrive as strings and are converted according to the function’s type hints, and 7.5 adds support for Python’s type statement aliases. Standard libraries such as BuiltIn, Collections, OperatingSystem, Process and String ship with the framework, while Browser, SeleniumLibrary, RequestsLibrary and AppiumLibrary are separate projects installed from PyPI. Browser library runs Playwright in a Node.js process behind its Python keywords. A remote library interface lets keywords be served from other languages, but Python is the natural home.
Output files are the product
Every run writes output.xml, or JSON if you name the output file with a .json extension, plus log.html and report.html generated from it. The log is a tree of every suite, test and keyword with arguments, timings, messages and embedded screenshots; the report summarises results by suite and tag. Rebot, the companion tool, regenerates reports from output files and merges several of them, which is how Pabot combines parallel runs and how a rerun of failed tests replaces the original results. The exit code is the number of failed tests, capped at 250, so CI fails without any extra wiring.
Variables, types and secrets
Variables can be set in files, from the command line with --variable, from environment variables with %{NAME} syntax, or inside tests with the VAR syntax added in 7.0. Since 7.3 a variable can declare a type, such as ${count: int}, and be converted on creation. Since 7.4 the Secret type hides a value in data and logs, even at trace level, and a secret can only be created from another secret or an environment variable, never a literal. Command-line values override file values, which is how one suite targets several environments without edits.
Strengths
What it does well
Readable reports with no setup
log.html lets anyone expand a failed test down to the keyword and argument that failed, with the screenshot Browser library or SeleniumLibrary captured at that moment. report.html gives pass rates per suite and tag. Both are self-contained HTML files, so a CI artefact is all a stakeholder needs to open them.
One framework across layers
Browser or SeleniumLibrary drive web applications, RequestsLibrary calls HTTP APIs, AppiumLibrary drives mobile apps, and Process and OperatingSystem cover command-line and file work. Because all of them are just keywords, one test can create data through an API, check it in the browser and verify a generated file, with one report covering every step.
Python functions as keywords
Anything awkward in Robot syntax, such as parsing a response, generating test data or querying a database, becomes a small Python function with type hints. It is testable with pytest, reusable across suites and called from Robot like any other keyword. This is the escape hatch that keeps keyword files readable.
Secret variables
The Secret type from 7.4 keeps passwords and tokens out of log files. Declare ${PASSWORD: Secret} from an environment variable, pass it to keywords that accept secrets, such as Browser library’s Fill Secret, and the value never appears in output. The release notes are explicit that this hides values rather than encrypting them.
Rerunning and merging failed tests
robot --rerunfailed reads an earlier output file and runs only the tests that failed, and rebot --merge folds the new results into the original, so the final report shows one result per test with both attempts recorded. It is a controlled alternative to blanket retries.
Tags, metadata and Markdown tests
Tags select what runs with --include and --exclude and drive the statistics in report.html. Robot Framework 7.5 adds per-test [Metadata], shown as separate fields in the log, and executes test data embedded in robotframework code blocks of .robot.md files, so a specification and its acceptance tests can live in one document.
Pricing
Robot Framework pricing and licensing
Robot Framework is free and open source under the Apache 2.0 licence, and the foundation page states that it stays that way. Development is funded by the non-profit Robot Framework Foundation, whose member organisations pay an annual fee tiered by how many Robot Framework users they have; membership is voluntary. Libraries such as Browser and SeleniumLibrary are separate open-source projects, so the real costs are infrastructure and the engineering time to build the keyword layer.
- Licence: Apache 2.0 for Robot Framework, SeleniumLibrary, Browser library and Pabot, as published on PyPI and in their repositories.
- Foundation membership: optional and priced by the number of Robot Framework users in the organisation. List prices on robotframework.org on 13 October 2026 ran from €500 to €12,000 a year, funding maintainers, ecosystem projects, documentation and the RoboCon conference.
- Infrastructure: browsers for web suites, devices or a cloud grid for mobile, and CI minutes. Pabot shortens runs but multiplies the browser processes running at once.
- Hidden cost: the keyword layer and library upgrades. Designing resource files takes skilled time up front, and each Browser library upgrade needs its Node.js side reinstalled.
Checked against the vendor’s own pages on 13 October 2026. Pricing changes; confirm on the official site before buying.
Getting started
Robot Framework tutorial: getting started
Setup, step by step
- Install Python 3.10 or later; Robot Framework supports 3.8 and up, but Browser library needs 3.10.
- Install Node.js 22, 24 or 26 for Browser library, or install robotframework-browser[bb], which bundles it.
- Install Robot Framework and Browser library with pip, then run rfbrowser init chromium.
- Save the example as tests/login.robot, separating cells with at least two spaces.
- Run robot --outputdir results tests and open results/log.html.
Install
pip install robotframework robotframework-browser
rfbrowser init chromium
robot --outputdir results tests
# SeleniumLibrary instead: pip install robotframework-seleniumlibraryA first example
*** Settings ***
Library Browser
*** Test Cases ***
Valid User Can Log In
New Page https://the-internet.herokuapp.com/login
Fill Text id=username tomsmith
Fill Text id=password SuperSecretPassword!
Click role=button[name="Login"]
# Get Text waits for the element, then retries the assertion
Get Text id=flash contains You logged into a secure area!What trips people up first
Whitespace. Cells are separated by two or more spaces, so Fill Text with one space before its selector becomes a keyword named Fill Text id=username that does not exist, and the error points at the keyword name rather than the spacing. Configure your editor to show whitespace, or use four spaces as a house rule. The second trap is the hash character, which starts a comment, so a CSS id selector must be written as id=username or escaped. With Browser library, the third is forgetting rfbrowser init after installing or upgrading, which leaves the Node.js side or the browsers missing.
In practice
Using Robot Framework in practice
Layering keywords in resource files
The structure that keeps Robot suites maintainable is three levels. Tests read as business steps and contain no selectors. Business keywords in resource files, such as Sign In As or Create Order For, combine page interactions. Library keywords from Browser or SeleniumLibrary sit at the bottom and are only called from resource files. Keep one resource file per area of the product, prefer role and data-testid selectors, and assert inside keywords with Browser library’s assertion operators, which retry. A redesign then changes a resource file, not every test, and a reviewer can read the test file alone.
# resources/orders.resource
*** Settings ***
Library Browser
*** Variables ***
${BASE_URL} http://localhost:3000
${PASSWORD: Secret} %{APP_PASSWORD}
*** Keywords ***
Sign In As
[Arguments] ${email}
New Page ${BASE_URL}/login
Fill Text data-testid=email ${email}
Fill Secret data-testid=password ${PASSWORD}
Click role=button[name="Sign in"]
Get Url contains /dashboard
Create Order For
[Arguments] ${product} ${quantity}=1
Click role=link[name="New order"]
Fill Text data-testid=product ${product}
Fill Text data-testid=quantity ${quantity}
Click role=button[name="Save"]
Order Count Should Be
[Arguments] ${expected}
Get Element Count data-testid=order-row == ${expected}
# tests/orders.robot
*** Settings ***
Resource ../resources/orders.resource
Suite Setup New Browser chromium # headless by default
Test Setup Sign In As [email protected]
*** Test Cases ***
New Order Appears In The List
Create Order For Blue mug quantity=2
Order Count Should Be 1Parallel runs with Pabot and controlled reruns
Pabot runs suites in parallel processes, by default as many as the larger of two and the CPU count, and merges the outputs into one log and report. It splits by suite unless you pass --testlevelsplit, which spreads individual tests but adds overhead, since each process starts its own browser. Make suites independent first: each should create its own data and sign in itself. PabotLib provides locks and shared value sets for the few resources that cannot be duplicated. For flaky infrastructure, rerun only the failed tests and merge them back rather than retrying everything; note that --rerunfailed stops with an error when nothing failed, so run it only after a failing run.
# Parallel by suite; add --testlevelsplit to split by test instead
pabot --processes 4 --outputdir results tests
# After a failing run: re-run only the failures...
robot --rerunfailed results/output.xml --output rerun.xml --outputdir results tests
# ...then merge, so each test shows once with both attempts recorded
rebot --merge --outputdir results --output merged.xml results/output.xml results/rerun.xmlRunning Robot Framework in GitHub Actions
The pipeline installs Python and Node.js, installs pinned packages, and lets rfbrowser init download Chromium with its system dependencies. Pass secrets as environment variables, which the Secret-typed variable in the resource file reads, so they never appear in the log. Robot’s exit code is the number of failed tests, so the job fails without extra configuration. Upload the whole results folder even when the run fails, because log.html with its embedded screenshots is what someone will open first. If installing Node.js is a problem on your runners, robotframework-browser[bb] bundles it and replaces rfbrowser init with rfbrowser install.
# .github/workflows/robot.yml
name: robot
on: [push, pull_request]
jobs:
robot:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: '3.13'
cache: pip
- uses: actions/setup-node@v7
with:
node-version: 24
# Pins robotframework, robotframework-browser and robotframework-pabot
- run: pip install -r requirements.txt
- run: rfbrowser init --with-deps chromium
- name: Run suites in parallel
run: pabot --processes 4 --outputdir results tests
env:
APP_PASSWORD: ${{ secrets.APP_PASSWORD }}
- uses: actions/upload-artifact@v7
if: ${{ !cancelled() }}
with:
name: robot-results
path: resultsChoosing Browser library or SeleniumLibrary
For new web suites, Browser library is the stronger default. It runs on Playwright, so actions auto-wait, strict mode fails a selector that matches more than one element, assertion operators on Get keywords retry, and pages and contexts opened in a test close automatically at the end of it. Its defaults are a 10 second timeout, 1 second of assertion retries and a screenshot on failure. SeleniumLibrary 6.9 runs on Selenium 4 with Selenium Manager handling drivers, has a 5 second default timeout, an implicit wait of 0 and Capture Page Screenshot on failure. Choose it when you need real Safari, an existing Selenium Grid or cloud provider, or when a large SeleniumLibrary suite already exists.
Upgrading to Robot Framework 7.5
Robot Framework 7.5 is a feature release with few incompatible changes for normal users, but it deprecates several things worth fixing now. The built-in Testdoc tool and the Telnet library are deprecated in favour of external projects. Tag patterns written like XORY must separate operators, as X OR Y, and the & operator gives way to AND. Regular expression matching in Collections will require a full match, and the list_ and time_ argument names become list and time in Robot Framework 8.0. If you are coming from 6.x, the [Return] setting has warned since 7.0 and singular section headers such as Test Case are deprecated. Run the suite once, read the deprecation warnings in the log and fix them before 8.0 removes them.
Pitfalls
Common pitfalls
A single space between a keyword and its argument
Why it happens: Cells are separated by two or more spaces, so a single space makes the argument part of the keyword name, and the error reports a missing keyword rather than bad spacing.
The fix: Use four spaces as a convention, make whitespace visible in the editor, and run a formatter such as Robocop’s in CI so spacing errors are caught before review.
Selectors cut short by the hash character
Why it happens: A hash starts a comment in Robot Framework data, so a CSS selector such as #username loses everything from the hash onwards.
The fix: Use the id strategy, as in id=username, prefer role or data-testid selectors, or escape the hash with a backslash where CSS is unavoidable.
Flat tests full of raw selectors
Why it happens: Writing library keywords straight into tests is quick at first, but every test then depends on markup, and a redesign breaks all of them at once.
The fix: Move interactions into resource file keywords named for user intent, keep tests to business steps, and review new tests for selectors that leaked into them.
Using Sleep to fix timing problems
Why it happens: Sleep hides a race on a fast machine and fails on a slow one, while adding dead time to every run.
The fix: Let Browser library’s auto-waiting and retrying assertions do the work, or with SeleniumLibrary use Wait Until Element Is Visible and similar keywords on the condition you need.
Old syntax from tutorials written before 7.0
Why it happens: Many examples use [Return], singular headers such as Test Case, and Set Variable where VAR fits. [Return] has warned since 7.0 and is kept until at least 8.0.
The fix: Use RETURN, plural section headers and the VAR syntax, and treat deprecation warnings in the log as tasks rather than noise.
Pabot runs that fail only in parallel
Why it happens: Suites that share accounts, data or ordering pass alone and collide when Pabot runs them together, which looks like random flakiness.
The fix: Give each suite its own data and login, use PabotLib locks for resources that cannot be duplicated, and run the full suite in parallel regularly so collisions surface early.
Upgrading Browser library with pip alone
Why it happens: Browser library has a Node.js side and Playwright browsers that pip does not update, so a pip upgrade leaves mismatched components.
The fix: After pip install -U robotframework-browser, run rfbrowser clean-node and then rfbrowser init, as the project’s update instructions describe.
Compared
Robot Framework alternatives compared
| Tool | Test format | Extension language | Browser automation | Parallel execution | Reports out of the box | Licence |
|---|---|---|---|---|---|---|
| Robot Framework | Keyword tables in plain text | Python; others via remote interface | Browser library or SeleniumLibrary | Pabot, a separate tool | log.html and report.html | Apache 2.0 |
| pytest | Python functions with assert | Python | Plugins, such as pytest-playwright | pytest-xdist plugin | Console output and JUnit XML | MIT |
| Cucumber | Gherkin scenarios plus step definitions | Java, JavaScript, Ruby and others | Any library, called from steps | Depends on the implementation | Formatters, including HTML | MIT |
| Playwright | TypeScript or JavaScript test functions | JS, TS, Python, Java, C# | Built in: Chromium, Firefox, WebKit | Workers and sharding built in | HTML report and trace viewer | Apache 2.0 |
FAQ
Frequently asked questions
What are the best Robot Framework alternatives?
The alternatives most often weighed against Robot Framework are pytest, Cucumber, Playwright and Selenium. The comparison on this page sets them side by side on test format, extension language, browser automation, parallel execution, reports out of the box and licence, and the verdict above says where Robot Framework is the wrong choice and which of them to pick instead.
Is Robot Framework free?
Yes. Robot Framework is open source under the Apache 2.0 licence, and so are its main libraries, Browser, SeleniumLibrary and Pabot. Development is funded by the non-profit Robot Framework Foundation through voluntary memberships priced by the number of users in an organisation. Your costs are infrastructure, such as browsers, devices and CI minutes, and the time to build a keyword layer.
Should I use Robot Framework or pytest?
Choose Robot Framework when non-programmers need to read or write tests, when one report must cover web, API and other layers, or for RPA tasks. Choose pytest when the people writing tests are developers, since plain Python is more direct and better supported by IDEs. The two combine well: write complex logic as Python libraries tested with pytest, and call them from Robot.
Should I use Browser library or SeleniumLibrary?
For a new web suite, Browser library: it runs on Playwright, with auto-waiting, strict selectors, retrying assertions and automatic page clean-up, and it is fast. Choose SeleniumLibrary when you need real Safari through WebDriver, an existing Selenium Grid or cloud grid, or when you maintain a large existing SeleniumLibrary suite. Both are actively released, Browser library every few weeks.
Can Robot Framework run tests in parallel?
Not on its own. Pabot, a separate open-source tool, runs suites in parallel processes and merges the results into one log and report. It splits by suite by default, or by test with --testlevelsplit, and PabotLib provides locks for shared resources. Suites must be independent first: tests that share data or depend on order fail unpredictably in parallel.
Do I need to know Python to use Robot Framework?
Not to write tests from existing keywords, which is the framework’s main appeal for mixed teams. Someone on the team does need Python to write custom libraries, debug library behaviour and keep the keyword layer clean, because logic written in Robot syntax becomes verbose quickly. A healthy team has a few people maintaining libraries and resource files and many writing tests.
What is new in Robot Framework 7.5?
Robot Framework 7.5 was released on 14 September 2026. It adds per-test [Metadata], custom console loggers via --console, executable tests in .robot.md Markdown files, type statement aliases for argument conversion, Markdown output for Libdoc and official Python 3.15 compatibility. It deprecates the built-in Testdoc tool, the Telnet library and some tag pattern forms, so read the warnings when you upgrade.
Is Robot Framework still worth learning in 2026?
Yes, where its strengths matter: mixed-skill teams, acceptance tests reviewed by non-developers, and RPA. It has steady releases, a foundation funding its maintainers, and Browser library gives it a modern Playwright-based web layer. For a developer-only team testing a single web application, learning Playwright or pytest directly is usually a better investment.
Can Robot Framework test APIs and mobile apps?
Yes, through libraries. RequestsLibrary covers HTTP APIs, Browser library has an HTTP keyword for calls inside a web test, and AppiumLibrary drives native and hybrid mobile apps through Appium. Because they are all keywords, one suite can mix layers, for example creating data through an API before checking it in the browser, with a single report.
Alternatives
Robot Framework alternatives worth weighing
Selenium
Open-source browser automation built on the W3C WebDriver standard, with official bindings for Java, Python, C#, Ruby and JavaScript.
Playwright
Microsoft browser automation with auto-waiting, network interception and parallel execution built in.
Cypress
JavaScript test framework running inside the browser, with a time-travelling debugger that is still the best in the category.
Resources
Where to go next
Keep going
Prepare, or get it done
Picking the wrong tool costs more than picking late.
QAble advises on toolchain decisions and then implements them, with engineers who have run these tools on real delivery. Start with a free QA audit.