Robot Framework Tutorial for Beginners: From Zero to Your First Test

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:

  1. Open Chromium (visible, because headless=False)
  2. Navigate to the demo page
  3. Assert the page title is "React TodoMVC"
  4. Close the browser
  5. Generate results in output.xml, log.html, and report.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 screenshots
  • report.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:

  1. Read the Browser Library documentation — it has 200+ keywords for every browser interaction
  2. Explore other libraries — RequestsLibrary for API testing, DatabaseLibrary for database verification
  3. Write custom Python keywords — for complex logic that keyword syntax does not handle cleanly
  4. Set up parallel execution with pabot — for large test suites
  5. 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.

Read more