Robot Framework Tutorial for Beginners: From Zero to Your First Test
Robot Framework is an open-source test automation framework that uses plain English keyword syntax, making tests readable by developers and non-developers alike. It integrates with Playwright, Selenium, REST APIs, databases, and nearly any system. This tutorial takes you from installation to running your first browser test.
Key Takeaways
Robot Framework uses readable keyword syntax. Tests read like English: Click Button Submit Order. This makes tests understandable by product managers, QA analysts, and developers — not just whoever wrote them.
It is framework-agnostic. Robot Framework is a thin orchestration layer. You use libraries underneath for specific capabilities — Browser (Playwright), SeleniumLibrary, RequestsLibrary, DatabaseLibrary, and many others.
The keyword abstraction is its superpower. You build high-level keywords from lower-level ones, creating a test language that matches your domain. Complete Checkout can encapsulate 20 lower-level steps.
HelpMeTest runs on Robot Framework and Playwright. Tests written for HelpMeTest use the same Robot Framework syntax, so everything you learn here applies directly.
Robot Framework is an open-source test automation framework with a keyword-driven syntax that makes tests readable without deep programming knowledge. It has been around since 2008, is maintained by the Robot Framework Foundation, and is trusted by organizations from Nokia to NASA.
This tutorial starts from the beginning: what Robot Framework is, how to install it, and how to write your first real automated test. By the end, you will have a working test suite that runs in a browser using Playwright.
What Is Robot Framework?
Robot Framework is a generic test automation framework. It does not actually drive browsers, call APIs, or connect to databases itself — it provides a structured way to write and execute tests that call libraries which do those things.
Think of it as a language layer on top of your automation libraries:
Your Test (Robot Framework keywords)
|
| calls
v
Browser Library (Playwright)
|
| drives
v
Chrome / Firefox / WebKit
The test you write says: Click Button Submit Order. Robot Framework parses this, finds the Click Button keyword in the Browser Library, and executes it. The Browser Library uses Playwright to find the button and click it.
This separation means you can write tests that read like plain English, and the implementation details live in the library.
Why Use Robot Framework?
Readable tests: A Robot Framework test file reads like a specification document. Business stakeholders can read tests and confirm they describe the right behavior.
Rich ecosystem: Libraries exist for web browsers, REST APIs, SQL databases, SSH, FTP, Excel, PDF, mobile apps, and much more. If you need to automate it, there is probably a Robot Framework library for it.
Keyword abstraction: You build a vocabulary of reusable keywords that match your domain. Once you have Complete Checkout as a keyword, tests are self-documenting.
Flexible reporting: Robot Framework generates detailed HTML reports and XML output that integrate with every major CI system.
No programming required for basic tests: The keyword syntax is accessible to QA analysts and business analysts who are not programmers. Programmers can write complex custom keywords in Python when needed.
Installation
Robot Framework requires Python 3.8+. Check your Python version first:
python3 --version
# Python 3.11.5
Install Robot Framework
pip install robotframework
Verify the installation:
robot --version
# Robot Framework 7.0 (Python 3.11.5 on darwin)
Install the Browser Library (Playwright Integration)
For browser automation, we use the Browser Library, which wraps Microsoft's Playwright:
pip install robotframework-browser
rfbrowser init
The rfbrowser init command downloads Playwright's browser binaries (Chromium, Firefox, WebKit). This takes a couple of minutes on first run.
Install Additional Useful Libraries
# For HTTP/REST API testing
pip install robotframework-requests
<span class="hljs-comment"># For YAML and JSON handling
pip install robotframework-jsonlibrary
<span class="hljs-comment"># For working with strings and dates
<span class="hljs-comment"># (BuiltIn and Collections are included with Robot Framework)
Project Structure
Create a directory for your tests:
my-tests/
tests/
login.robot
checkout.robot
resources/
keywords.robot
variables.robot
results/
(generated by Robot Framework)
Your First Test File
Create tests/login.robot:
*** Settings ***
Library Browser
*** Test Cases ***
User Can Log In
New Browser chromium headless=False
New Page https://demo.playwright.dev/todomvc/
Get Title == React TodoMVC
Close Browser
Run it:
robot tests/login.robot
Robot Framework will:
- Open Chromium (visible, because
headless=False) - Navigate to the demo page
- Assert the page title is "React TodoMVC"
- Close the browser
- Generate results in
output.xml,log.html, andreport.html
Open report.html in your browser to see the test results.
Understanding Robot Framework Syntax
The Four Sections
Every .robot file can contain four sections:
*** Settings ***
# Configuration: imports, setup, teardown, documentation
*** Variables ***
# Test-level variable definitions
*** Test Cases ***
# The actual tests
*** Keywords ***
# Custom keyword definitions
Sections start with *** Section Name *** and can appear in any order. Only *** Test Cases *** is required.
Keyword Arguments
Keywords accept arguments separated by four or more spaces (or a tab):
*** Test Cases ***
Example Test
Log Hello, World! # One argument
Sleep 2s # One argument (2 seconds)
New Browser chromium headless=True # Two arguments
The spacing is critical: Robot Framework uses two spaces (or fewer) as part of a value, and four or more spaces as argument separators. Use consistent spacing — (4 spaces) between a keyword and its arguments is the standard.
Variables
Variables use ${...} syntax for scalar values and @{...} for lists:
*** Variables ***
${BASE_URL} https://shop.example.com
${USERNAME} testuser@example.com
${PASSWORD} Password123
@{VALID_SIZES} Small Medium Large
*** Test Cases ***
Login Test
Go To ${BASE_URL}/login
Fill Text #email ${USERNAME}
Fill Text #password ${PASSWORD}
Click [type="submit"]
Variables are case-insensitive. ${base_url} and ${BASE_URL} are the same variable.
Comments
# This is a comment
Test Case Name
Keyword # Inline comment
Writing Real Browser Tests
Let me walk through a complete E2E test for a login flow.
Setup and Teardown
*** Settings ***
Library Browser
Suite Setup Open The Browser
Suite Teardown Close The Browser
Test Setup Go To ${BASE_URL}/login
Test Teardown Take Screenshot
*** Variables ***
${BASE_URL} https://your-app.example.com
${BROWSER} chromium
*** Keywords ***
Open The Browser
New Browser ${BROWSER} headless=True
New Context viewport={'width': 1280, 'height': 720}
New Page
Close The Browser
Close Browser
Suite Setup runs once before all tests in the file. Suite Teardown runs once after all tests. Test Setup runs before each individual test. Test Teardown runs after each test — even if the test fails, which makes it ideal for taking screenshots on failure.
Writing the Login Test
*** Test Cases ***
Successful Login With Valid Credentials
Fill Text #email ${USERNAME}
Fill Text #password ${PASSWORD}
Click [type="submit"]
Get URL == ${BASE_URL}/dashboard
Get Element text=Welcome back
Login Fails With Wrong Password
Fill Text #email ${USERNAME}
Fill Text #password wrongpassword
Click [type="submit"]
Get URL == ${BASE_URL}/login
Get Element text=Invalid email or password
Login Requires Email Field
Fill Text #password ${PASSWORD}
Click [type="submit"]
Get Element css=.error-message # Error appears without email
Browser Library Keywords Reference
The Browser Library provides keywords that wrap Playwright's capabilities:
| Keyword | Description | Example |
|---|---|---|
New Browser |
Opens a browser | New Browser chromium |
New Page |
Opens a new tab | New Page https://example.com |
Go To |
Navigate to URL | Go To /checkout |
Click |
Click an element | Click [data-testid="submit"] |
Fill Text |
Type into an input | Fill Text #email user@test.com |
Get Text |
Get element's text | ${text}= Get Text h1 |
Get Element |
Assert element exists | Get Element .success-message |
Get URL |
Assert current URL | Get URL == /dashboard |
Wait For Elements State |
Wait for element state | Wait For Elements State .loader hidden |
Take Screenshot |
Capture screenshot | Take Screenshot |
Keyboard Key |
Press a key | Keyboard Key press Enter |
Select Options By |
Select from dropdown | Select Options By #country text United States |
Upload File By Selector |
Upload a file | Upload File By Selector #file /path/to/file.pdf |
Assertions
The Browser Library's assertion keywords use a comparison operator pattern:
# String assertions
Get Text h1 == Welcome to the Dashboard
Get Text .subtitle contains Hello
# URL assertions
Get URL == https://shop.example.com/checkout
Get URL matches .*checkout.*
# Element state assertions
Get Element States [data-testid="submit"] contains enabled
Get Element States .spinner contains hidden
# Attribute assertions
Get Attribute img.logo src == /static/logo.png
Custom Keywords
Custom keywords let you build reusable, high-level actions that abstract away the implementation details.
Defining Keywords
*** Keywords ***
Log In As User
[Arguments] ${email} ${password}
Go To ${BASE_URL}/login
Fill Text #email ${email}
Fill Text #password ${password}
Click [type="submit"]
Wait For Elements State .dashboard-header visible
Add Product To Cart
[Arguments] ${product_name}
Click text=${product_name}
Click [data-testid="add-to-cart"]
Wait For Elements State .cart-count visible
Complete Checkout
[Arguments] ${address} ${card_number}
Click [data-testid="checkout-btn"]
Fill Text [name="address"] ${address}
Fill Text [name="card"] ${card_number}
Click [data-testid="place-order"]
Get Element text=Order Confirmed
Using Keywords in Tests
*** Test Cases ***
User Can Purchase A Product
Log In As User testuser@example.com Password123
Add Product To Cart Blue Widget
Complete Checkout 123 Main St 4242424242424242
This test reads exactly like a user story acceptance criteria. A product manager can read it and confirm it tests the right behavior.
Keyword Arguments with Defaults
*** Keywords ***
Log In As User
[Arguments] ${email}=${DEFAULT_USER} ${password}=${DEFAULT_PASS}
Go To ${BASE_URL}/login
Fill Text #email ${email}
Fill Text #password ${password}
Click [type="submit"]
*** Test Cases ***
Admin User Can Access Settings
Log In As User email=admin@example.com password=AdminPass
Click text=Settings
Regular User Cannot Access Settings
Log In As User # Uses defaults
Get Element text=Dashboard
Get Element Count text=Settings == 0
Return Values from Keywords
*** Keywords ***
Get Cart Item Count
${count}= Get Text .cart-badge
RETURN ${count}
*** Test Cases ***
Cart Updates When Item Added
${initial_count}= Get Cart Item Count
Click [data-testid="add-to-cart"]
${new_count}= Get Cart Item Count
Should Be True ${new_count} == ${initial_count} + 1
Variables and Resource Files
Variable Types
*** Variables ***
# Scalar (single value)
${BASE_URL} https://shop.example.com
${TIMEOUT} 30s
${MAX_RETRIES} 3
# List (multiple values)
@{VALID_COUNTRIES} USA Canada UK Australia
# Dictionary
&{ADMIN_USER}
... email=admin@example.com
... password=AdminPass123
... role=admin
Resource Files
Split your keywords and variables into shared resource files:
# resources/common.robot
*** Settings ***
Library Browser
*** Variables ***
${BASE_URL} https://shop.example.com
${HEADLESS} True
*** Keywords ***
Open Browser Session
New Browser chromium headless=${HEADLESS}
New Context
New Page
Import in your test files:
# tests/checkout.robot
*** Settings ***
Resource ../resources/common.robot
*** Test Cases ***
Checkout Flow
Open Browser Session
Log In As User testuser@example.com pass123
Add Product To Cart Widget Pro
Complete Checkout ...
Environment-Specific Variables
Use variable files to manage environment-specific configuration:
# config/staging.py
BASE_URL = "https://staging.example.com"
USERNAME = "stage-user@example.com"
PASSWORD = "StagePass123"
robot --variablefile config/staging.py tests/
Or use environment variables:
*** Settings ***
Library OperatingSystem
*** Variables ***
${BASE_URL} %{APP_URL=https://localhost:3000} # Default if env var not set
Test Data and Data-Driven Testing
Robot Framework supports data-driven testing with the [Template] syntax:
*** Test Cases ***
Login Validation
[Template] Attempt Login And Verify Result
valid@example.com ValidPass123 /dashboard success
valid@example.com wrongpassword /login Invalid password
notanemail ValidPass123 /login Invalid email
${EMPTY} ValidPass123 /login Email is required
valid@example.com ${EMPTY} /login Password is required
*** Keywords ***
Attempt Login And Verify Result
[Arguments] ${email} ${password} ${expected_url} ${expected_message}
Go To ${BASE_URL}/login
Run Keyword If '${email}' != '${EMPTY}' Fill Text #email ${email}
Run Keyword If '${password}' != '${EMPTY}' Fill Text #password ${password}
Click [type="submit"]
Get URL contains ${expected_url}
Get Element text=${expected_message}
Each row in the test case becomes a separate test run with different inputs.
Running Tests
Basic Execution
# Run all tests in a directory
robot tests/
<span class="hljs-comment"># Run a specific file
robot tests/checkout.robot
<span class="hljs-comment"># Run tests matching a tag
robot --include smoke tests/
<span class="hljs-comment"># Run tests excluding a tag
robot --exclude slow tests/
<span class="hljs-comment"># Run tests matching a name pattern
robot --<span class="hljs-built_in">test <span class="hljs-string">"User Can*" tests/
Tags for Test Organization
*** Test Cases ***
Quick Smoke Test
[Tags] smoke fast
Go To ${BASE_URL}
Get Element text=Welcome
Full Checkout Flow
[Tags] regression slow checkout
# ... detailed test
# Run only smoke tests
robot --include smoke tests/
<span class="hljs-comment"># Run regression but not slow tests
robot --include regression --exclude slow tests/
Parallel Execution with Pabot
For large test suites, use pabot (Parallel Robot Framework Executor):
pip install robotframework-pabot
# Run with 4 parallel processes
pabot --processes 4 tests/
Output and Reports
After a test run, Robot Framework generates three output files:
output.xml— raw test data in XML format (for CI integration)log.html— detailed step-by-step log with screenshotsreport.html— summary report with pass/fail statistics
Open log.html after a failing test run to see exactly which step failed, the screenshot captured at failure, and the full execution trace.
CI/CD Integration
GitHub Actions
# .github/workflows/robot-tests.yml
name: Robot Framework Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install robotframework robotframework-browser
rfbrowser init --browser chromium
- name: Run tests
run: robot --outputdir results tests/
- name: Upload results
if: always()
uses: actions/upload-artifact@v4
with:
name: robot-results
path: results/
Generating JUnit XML for CI Integration
# Generate JUnit-compatible XML for Jenkins, GitHub Actions, etc.
robot --output output.xml tests/
rebot --xunit results.xml output.xml
Most CI platforms can parse JUnit XML to display test results directly in the build summary.
Robot Framework with HelpMeTest
HelpMeTest uses Robot Framework as its test execution engine, enhanced with AI-powered keywords. If you have been following this tutorial, you are already familiar with the fundamentals.
HelpMeTest tests use the same .robot syntax with additional keywords for AI capabilities:
*** Settings ***
Library Browser
*** Test Cases ***
AI-Assisted Checkout Test
New Browser chromium
New Page https://shop.example.com
# Standard Browser Library keywords
Fill Text #email user@example.com
Fill Text #password Password123
Click [type="submit"]
# HelpMeTest AI keywords
Check For Visual Flaws css=.checkout-form
# Self-healing: natural language actions
Click the checkout button
Verify the order confirmation is shown
The Click the checkout button keyword is interpreted by the AI — it reads the current page and identifies the element that semantically represents "the checkout button," regardless of its current CSS class or ID. This is the self-healing behavior described in the self-healing tests guide.
Common Mistakes and How to Avoid Them
Spacing errors: Robot Framework uses spaces to separate keyword names from arguments. Too few spaces in the wrong place can make Robot Framework think you have named your keyword something unexpected.
# WRONG: only 2 spaces — "Get Text h1" is parsed as one long keyword name
Get Text h1
# CORRECT: 4+ spaces separate keyword from argument
Get Text h1
Forgetting to wait: Clicking a button that triggers navigation and immediately asserting the new page URL will fail if the page has not loaded yet.
# WRONG: may fail if page hasn't loaded
Click [data-testid="login"]
Get URL == /dashboard
# CORRECT: wait for the navigation
Click [data-testid="login"]
Wait For Elements State .dashboard-header visible
Get URL == /dashboard
Hardcoded sleeps: Sleep 5s is almost never the right solution. Use explicit waits for the condition you care about.
Not using resource files: As your test suite grows, duplicate keywords across files become a maintenance problem. Move shared keywords to resources/keywords.robot early.
Selector fragility: Generic selectors like css=button:nth-child(2) break easily. Use data-testid attributes or semantic selectors like text=Submit Order.
Frequently Asked Questions
Is Robot Framework hard to learn?
The basic keyword syntax is one of the easiest testing frameworks to learn — tests read like English, and getting started requires minimal programming knowledge. Advanced features like custom Python libraries and complex data structures have a steeper curve.
Does Robot Framework work with Python?
Yes. Robot Framework is written in Python, and you can write custom keyword libraries in Python. This is how advanced users extend Robot Framework with domain-specific capabilities.
What is the difference between Robot Framework and Selenium?
Robot Framework is a test framework (orchestration layer). Selenium is a browser automation library. SeleniumLibrary is a Robot Framework library that wraps Selenium. Similarly, Browser Library wraps Playwright. You use Robot Framework to write tests and choose which browser automation library to use underneath.
Should I use SeleniumLibrary or Browser Library?
For new projects in 2025, use Browser Library (Playwright). It is faster, more reliable, supports modern web features, and is actively developed. SeleniumLibrary is better if you need to test with Internet Explorer or have an existing Selenium setup you want to migrate gradually.
Can Robot Framework test APIs?
Yes. RequestsLibrary enables HTTP API testing from Robot Framework:
*** Settings ***
Library RequestsLibrary
*** Test Cases ***
API Returns User Data
Create Session api https://api.example.com
${response}= GET On Session api /users/1
Should Be Equal As Integers ${response.status_code} 200
Should Be Equal ${response.json()['name']} Alice
How does Robot Framework compare to Playwright or Cypress?
Playwright and Cypress are complete testing frameworks that handle both the browser automation and the test runner. Robot Framework is a test framework that uses libraries (like Browser Library, which uses Playwright) for browser automation. Robot Framework's main advantages are its keyword abstraction layer and its readability — tests look like documentation rather than code.
Next Steps
You now have the fundamentals to write Robot Framework tests. Here is how to go deeper:
- Read the Browser Library documentation — it has 200+ keywords for every browser interaction
- Explore other libraries — RequestsLibrary for API testing, DatabaseLibrary for database verification
- Write custom Python keywords — for complex logic that keyword syntax does not handle cleanly
- Set up parallel execution with pabot — for large test suites
- Integrate with HelpMeTest — to add AI-powered keywords and cloud execution to your Robot Framework tests
The Robot Framework ecosystem is large and active. Once you understand the core keyword model, everything else builds on it.