agentleFS
MathiasPaulenkoMathiasPaulenko/ai-toolkit/skills/robot-framework/SKILL.md

robot-framework

Skill2 starsChanged 3 months agoMITView on GitHub

Production-grade skill for Robot Framework keyword-driven testing. Covers project structure, keywords, variables, libraries (Selenium, Requests, Database), resources, setup/teardown, tags, CLI execution, and CI/CD integration.

  • Installs packages
Files
SKILL.md

Robot Framework Skill

Description

Comprehensive skill for Robot Framework, the leading keyword-driven test automation framework in Python. Covers project structure, custom and built-in keywords, variable scopes, resource and variable files, library integration (Selenium, Requests, Database), setup/teardown patterns, tag-based execution, command-line options, and CI/CD integration.

Table of Contents

  1. Project Setup
  2. Test Case Syntax
  3. Keywords
  4. Variables
  5. Libraries
  6. Resource & Variable Files
  7. Setup & Teardown
  8. Tags
  9. Execution & CLI
  10. CI/CD Integration
  11. Best Practices Checklist
  12. Common Pitfalls
  13. References

When to Invoke

  • Creating or refactoring a Robot Framework test suite
  • Writing keyword-driven tests for web, API, or database validation
  • Structuring a Robot Framework project with resources and libraries
  • Implementing custom keywords in Python or Robot syntax
  • Managing variables across different scopes (test, suite, global)
  • Integrating SeleniumLibrary, RequestsLibrary, or DatabaseLibrary
  • Configuring setup/teardown at test, suite, or global level
  • Using tags to organize and filter test execution
  • Running tests via CLI with custom options and listeners
  • Integrating Robot Framework into Jenkins, GitHub Actions, or GitLab CI

1. Project Setup

Directory Layout

robot-project/
  tests/
    api/
      login_api.robot
      users_api.robot
    ui/
      login_ui.robot
      checkout_ui.robot
  resources/
    keywords/
      common.robot
      api_keywords.robot
      ui_keywords.robot
    pages/
      login_page.robot
      home_page.robot
    variables/
      global_variables.py
      test_data.yaml
    locators/
      login_locators.yaml
  libraries/
    CustomLibrary.py
  config/
    environments.yaml
  results/
  requirements.txt
  run.sh

requirements.txt

robotframework>=6.1.0
robotframework-seleniumlibrary>=6.1.0
robotframework-requests>=0.9.5
robotframework-databaselibrary>=1.3.0
robotframework-pabot>=2.15.0

Installation

pip install -r requirements.txt

2. Test Case Syntax

Basic Structure

*** Settings ***
Documentation    Test suite for user login functionality
Resource         ../resources/keywords/common.robot
Test Setup       Open Browser To Login Page
Test Teardown    Close Browser

*** Test Cases ***
Valid Login
    [Documentation]    Verify that a valid user can log in successfully
    [Tags]    smoke    regression    api
    Input Username    ${VALID_USER}
    Input Password    ${VALID_PASSWORD}
    Click Login Button
    Welcome Page Should Be Open

Invalid Login With Wrong Password
    [Documentation]    Verify login fails with incorrect password
    [Tags]    regression    negative
    Input Username    ${VALID_USER}
    Input Password    wrongpassword
    Click Login Button
    Error Message Should Be Visible    Invalid credentials

BDD-Style Syntax

*** Test Cases ***
User Can Add Item To Cart
    Given User Is Logged In
    When User Adds Product "Headphones" To Cart
    Then Cart Should Contain "Headphones"
    And Cart Total Should Be "$99.99"

3. Keywords

Built-in Keywords

*** Test Cases ***
Built-in Examples
    ${result} =    Evaluate    2 + 2
    Should Be Equal As Numbers    ${result}    4

    ${list} =    Create List    apple    banana    cherry
    Should Contain    ${list}    banana

    ${dict} =    Create Dictionary    name=John    age=30
    Dictionary Should Contain Key    ${dict}    name

    Run Keyword If    ${result} > 3    Log    Result is greater than 3
    Run Keyword Unless    ${result} == 4    Fail    Unexpected result

    Wait Until Keyword Succeeds    5x    1s    Check Element Is Visible    id:submit

User-Defined Keywords (Robot Syntax)

*** Keywords ***
Input Username
    [Arguments]    ${username}
    [Documentation]    Enters the given username into the username field
    Wait Until Element Is Visible    ${LOGIN.USERNAME_FIELD}
    Input Text    ${LOGIN.USERNAME_FIELD}    ${username}

Input Password
    [Arguments]    ${password}
    Input Text    ${LOGIN.PASSWORD_FIELD}    ${password}

Click Login Button
    Click Button    ${LOGIN.SUBMIT_BUTTON}

Welcome Page Should Be Open
    Location Should Be    ${WELCOME_URL}
    Page Should Contain    Welcome

Login With Credentials
    [Arguments]    ${username}    ${password}
    Input Username    ${username}
    Input Password    ${password}
    Click Login Button

Custom Keywords in Python

# libraries/CustomLibrary.py
from robot.api.deco import keyword
import hashlib


class CustomLibrary:
    ROBOT_LIBRARY_SCOPE = "GLOBAL"

    def __init__(self):
        self.session = None

    @keyword("Generate MD5 Hash")
    def generate_md5(self, text: str) -> str:
        """Generate MD5 hash of the given text."""
        return hashlib.md5(text.encode()).hexdigest()

    @keyword("Format Currency")
    def format_currency(self, amount: float, symbol: str = "$") -> str:
        """Format amount as currency string."""
        return f"{symbol}{amount:,.2f}"

    @keyword("Validate Email Format")
    def validate_email(self, email: str) -> bool:
        """Check if email format is valid."""
        import re
        pattern = r"^[^@]+@[^@]+\.[^@]+$"
        return bool(re.match(pattern, email))

Keyword Arguments

*** Keywords ***
Create User Via API
    [Arguments]    ${name}    ${email}    ${role}=user    ${status}=active
    ${payload} =    Create Dictionary
    ...    name=${name}
    ...    email=${email}
    ...    role=${role}
    ...    status=${status}
    ${response} =    POST On Session    api    /users    json=${payload}
    Should Be Equal As Strings    ${response.status_code}    201
    RETURN    ${response.json()['id']}

Keyword Teardown

*** Keywords ***
Create Temporary File
    [Arguments]    ${content}
    [Teardown]    Remove File    ${path}
    ${path} =    Join Path    ${TEMPDIR}    temp.txt
    Create File    ${path}    ${content}
    RETURN    ${path}

4. Variables

Variable Scopes

PrefixScopeExample
${VAR}Global / Test case${VALID_USER}
@{LIST}List variable@{USERS}
&{DICT}Dictionary variable&{CREDENTIALS}
$${VAR}Environment variable$${PATH}
%{VAR}Operating system variable%{HOME}

Scalar Variables

*** Variables ***
${URL}              https://api.example.com
${BROWSER}          chrome
${TIMEOUT}          10
${VALID_USER}       testuser@example.com
${VALID_PASSWORD}   TestPassword123!

List Variables

*** Variables ***
@{BROWSERS}         chrome    firefox    edge
@{HTTP_METHODS}     GET       POST       PUT       DELETE
*** Test Cases ***
Test All Browsers
    FOR    ${browser}    IN    @{BROWSERS}
        Open Browser    ${URL}    ${browser}
        Log In With Valid Credentials
        Close Browser
    END

Dictionary Variables

*** Variables ***
&{VALID_CREDENTIALS}    username=testuser    password=TestPass123
&{HEADERS}                Content-Type=application/json    Accept=application/json
*** Test Cases ***
Login With Dictionary Credentials
    Input Text    ${LOGIN.USERNAME}    ${VALID_CREDENTIALS}[username]
    Input Text    ${LOGIN.PASSWORD}    ${VALID_CREDENTIALS}[password]

Variable Files (Python)

# variables/global_variables.py
import os

URL = os.environ.get("BASE_URL", "https://staging.example.com")
BROWSER = os.environ.get("BROWSER", "chrome")
TIMEOUT = int(os.environ.get("TIMEOUT", "10"))

VALID_USER = os.environ.get("TEST_USER", "testuser@example.com")
VALID_PASSWORD = os.environ.get("TEST_PASSWORD", "TestPassword123!")
*** Settings ***
Variables    ../variables/global_variables.py

Variable Files (YAML)

# variables/test_data.yaml
users:
  admin:
    username: admin@example.com
    password: AdminPass123
    role: administrator
  editor:
    username: editor@example.com
    password: EditorPass456
    role: editor
*** Settings ***
Variables    ../variables/test_data.yaml

*** Test Cases ***
Login As Admin
    Log In    ${users}[admin][username]    ${users}[admin][password]

5. Libraries

SeleniumLibrary (UI Testing)

*** Settings ***
Library    SeleniumLibrary    timeout=10    implicit_wait=2

*** Keywords ***
Open Browser To Login Page
    Open Browser    ${URL}    ${BROWSER}
    Maximize Browser Window
    Set Selenium Speed    0.5s
    Go To    ${URL}/login
    Title Should Be    Login

Wait And Click Element
    [Arguments]    ${locator}
    Wait Until Element Is Visible    ${locator}    timeout=${TIMEOUT}
    Click Element    ${locator}

Capture Screenshot On Failure
    [Arguments]    ${filename}
    Capture Page Screenshot    ${filename}

RequestsLibrary (API Testing)

*** Settings ***
Library    RequestsLibrary

*** Keywords ***
Create API Session
    Create Session    api    ${URL}    headers=${HEADERS}
    ${token} =    Get Auth Token
    Set To Dictionary    ${HEADERS}    Authorization=Bearer ${token}

Get Auth Token
    ${payload} =    Create Dictionary    username=${VALID_USER}    password=${VALID_PASSWORD}
    ${response} =    POST On Session    api    /auth/login    json=${payload}
    Should Be Equal As Strings    ${response.status_code}    200
    RETURN    ${response.json()['token']}

Get User By ID
    [Arguments]    ${user_id}
    ${response} =    GET On Session    api    /users/${user_id}
    Should Be Equal As Strings    ${response.status_code}    200
    RETURN    ${response.json()}

DatabaseLibrary (Database Testing)

*** Settings ***
Library    DatabaseLibrary

*** Keywords ***
Connect To Test Database
    Connect To Database
    ...    pymysql
    ...    ${DB_NAME}
    ...    ${DB_USER}
    ...    ${DB_PASSWORD}
    ...    ${DB_HOST}
    ...    ${DB_PORT}

Verify User Exists In Database
    [Arguments]    ${email}
    ${result} =    Query    SELECT id FROM users WHERE email = '${email}'
    Should Not Be Empty    ${result}

Built-in Libraries Summary

LibraryPurpose
BuiltInCore keywords (log, evaluate, run keyword if, etc.)
CollectionsList/dictionary operations
DateTimeDate and time manipulation
OperatingSystemFile system, environment variables
ProcessRun external processes
ScreenshotTake screenshots
StringString manipulation
XMLXML parsing and validation

6. Resource & Variable Files

Resource File Structure

# resources/keywords/common.robot
*** Settings ***
Documentation    Common keywords used across test suites
Library          SeleniumLibrary
Library          RequestsLibrary
Variables        ../variables/global_variables.py

*** Keywords ***
Log In With Valid Credentials
    Input Text    ${LOGIN.USERNAME}    ${VALID_USER}
    Input Text    ${LOGIN.PASSWORD}    ${VALID_PASSWORD}
    Click Button    ${LOGIN.SUBMIT}
    Welcome Page Should Be Open

Log In
    [Arguments]    ${username}    ${password}
    Input Text    ${LOGIN.USERNAME}    ${username}
    Input Text    ${LOGIN.PASSWORD}    ${password}
    Click Button    ${LOGIN.SUBMIT}

Log Out
    Click Element    ${NAV.LOGOUT}
    Page Should Contain    You have been logged out

Page Object Pattern

# resources/pages/login_page.robot
*** Variables ***
${LOGIN.URL}              /login
${LOGIN.USERNAME}         id:username
${LOGIN.PASSWORD}         id:password
${LOGIN.SUBMIT}           id:submit-button
${LOGIN.ERROR}            css:.error-message
${LOGIN.SUCCESS}          css:.success-message

*** Keywords ***
Open Login Page
    Go To    ${BASE_URL}${LOGIN.URL}
    Wait Until Element Is Visible    ${LOGIN.USERNAME}

Input Username
    [Arguments]    ${username}
    Input Text    ${LOGIN.USERNAME}    ${username}

Input Password
    [Arguments]    ${password}
    Input Text    ${LOGIN.PASSWORD}    ${password}

Submit Login Form
    Click Button    ${LOGIN.SUBMIT}

Error Message Should Be Visible
    [Arguments]    ${expected_message}
    Wait Until Element Is Visible    ${LOGIN.ERROR}
    Element Should Contain    ${LOGIN.ERROR}    ${expected_message}

Importing Resources

*** Settings ***
Resource    ../resources/keywords/common.robot
Resource    ../resources/pages/login_page.robot
Resource    ../resources/pages/home_page.robot
Variables   ../variables/global_variables.py
Variables   ../variables/test_data.yaml

7. Setup & Teardown

Levels

*** Settings ***
# Suite-level: runs once per suite file
Suite Setup       Connect To Test Database
Suite Teardown    Disconnect From Database

# Test-level: runs before/after each test case
Test Setup        Open Browser To Login Page
Test Teardown     Close Browser

# Task-level (in RPA): runs before/after each task
Task Setup        Log In As Admin
Task Teardown     Log Out

Named Setup/Teardown

*** Keywords ***
Prepare Test Environment
    Connect To Database
    Clean Test Data
    Seed Test Users

Clean Up Test Environment
    Rollback Transactions
    Disconnect From Database

*** Settings ***
Suite Setup       Run Keywords    Prepare Test Environment    AND    Log    Suite setup complete
Suite Teardown    Run Keywords    Clean Up Test Environment    AND    Log    Suite teardown complete

Conditional Teardown

*** Test Cases ***
Create Order Test
    [Setup]    Log In As Admin
    [Teardown]    Run Keyword If Test Failed    Cancel Order    ${ORDER_ID}
    ${ORDER_ID} =    Create Order
    Verify Order Exists    ${ORDER_ID}

8. Tags

Tag Syntax

*** Test Cases ***
Valid Login
    [Tags]    smoke    regression    critical    ui
    ...       jira:PROJ-123
    Login With Credentials    ${VALID_USER}    ${VALID_PASSWORD}
    Welcome Page Should Be Open

Tagging at Suite Level

*** Settings ***
Default Tags    regression    api
Force Tags      sprint-42

Tag Patterns in CLI

# Include only smoke tests
robot --include smoke tests/

# Exclude slow tests
robot --exclude slow tests/

# Include smoke AND critical
robot --include smokeANDcritical tests/

# Include smoke OR critical
robot --include smokeORcritical tests/

# Exclude wip AND debug
robot --exclude wipORdebug tests/

# Combine include and exclude
robot --include regression --exclude slow tests/

# Tag patterns with wildcards
robot --include sprint* tests/

Tagging via Python Listener

# listeners/TagListener.py
from robot.api import SuiteVisitor


class TagListener(SuiteVisitor):
    def start_suite(self, suite):
        for test in suite.tests:
            if "api" in suite.name.lower():
                test.tags.add("api-suite")

9. Execution & CLI

Basic Execution

# Run all tests in directory
robot tests/

# Run specific test file
robot tests/ui/login.robot

# Run specific test case
robot --test "Valid Login" tests/ui/login.robot

# Run multiple test suites
robot tests/ui/ tests/api/

Output Options

# Custom output directory
robot --outputdir results/ tests/

# Custom report names
robot --output results/output.xml --report results/report.html --log results/log.html tests/

# Generate only XML (for CI)
robot --output results/output.xml --report NONE --log NONE tests/

# Set log level
robot --loglevel DEBUG tests/

Variable Overrides

# Override variables from CLI
robot --variable BROWSER:firefox --variable URL:https://staging.example.com tests/

# Variable file
robot --variablefile variables/staging.py tests/

# Multiple variable files
robot --variablefile variables/common.py --variablefile variables/staging.py tests/

Parallel Execution (pabot)

# Run tests in parallel across 4 processes
pabot --processes 4 tests/

# Parallel with custom output
pabot --processes 4 --outputdir results/ tests/

# Parallel by suite
pabot --processes 4 --pabotlib tests/

Dry Run

# Validate syntax without executing keywords
robot --dryrun tests/

Listeners

# Custom listener for custom reporting
robot --listener listeners.AllureListener tests/

10. CI/CD Integration

GitHub Actions

# .github/workflows/robot-tests.yml
name: Robot Framework Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      selenium:
        image: selenium/standalone-chrome
        ports:
          - 4444:4444

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Run Robot Framework tests
        run: |
          robot \
            --variable BROWSER:headlesschrome \
            --variable SELENIUM_URL:http://localhost:4444/wd/hub \
            --outputdir results/ \
            --exclude wip \
            tests/

      - name: Upload results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: robot-results
          path: results/

Jenkins Pipeline

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                sh '''
                    robot \
                        --variable ENV:staging \
                        --outputdir results/ \
                        --exclude not_ready \
                        tests/
                '''
            }
        }
    }
    post {
        always {
            robot outputPath: 'results/'
        }
    }
}

GitLab CI

stages:
  - test

robot-tests:
  stage: test
  image: python:3.11
  services:
    - selenium/standalone-chrome
  script:
    - pip install -r requirements.txt
    - robot --outputdir results/ --exclude wip tests/
  artifacts:
    when: always
    paths:
      - results/
    reports:
      junit: results/output.xml

11. Best Practices Checklist

  • Use Page Object pattern: locators in dedicated .robot files, logic in keyword files
  • Keep test cases short and focused: one assertion per test
  • Use BDD naming: Given/When/Then in test case names
  • Extract reusable keywords to resource files
  • Use variables for all dynamic data (URLs, credentials, timeouts)
  • Store sensitive data in environment variables, never in repo
  • Use tag expressions to organize by layer (ui, api, db) and priority (smoke, regression)
  • Implement setup/teardown at the lowest possible scope
  • Use Wait Until Keyword Succeeds for flaky operations
  • Add [Documentation] to every test case and keyword
  • Use [Arguments] typing for keyword parameters
  • Return values from keywords using RETURN (or Return From Keyword in older versions)
  • Use Run Keyword And Ignore Error for non-critical steps
  • Implement custom Python libraries for complex logic
  • Use pabot for parallel execution in CI
  • Generate JUnit-compatible output for CI integration
  • Keep locators in YAML or dedicated files, not inline in keywords
  • Use Set Selenium Speed only for debugging, not in CI
  • Implement Listener for custom reporting (Allure, TestRail, etc.)
  • Version control .robot files; exclude results/ directory

12. Common Pitfalls

ProblemCauseSolution
Variable not foundWrong scope or missing importCheck *** Variables *** section or resource import
Keyword not foundMissing Resource or Library importVerify *** Settings *** imports
Element not foundTiming issue or wrong locatorUse Wait Until Element Is Visible with explicit timeout
Suite setup failedPrevious test left dirty stateImplement robust suite teardown
Slow test executionSleep or implicit waitsReplace Sleep with explicit waits
Duplicate keywordsSame name in multiple resourcesUse resource namespacing or unique names
Hardcoded credentialsValues in .robot filesMove to environment variables or encrypted files
Brittle locatorsXPath with dynamic IDsUse data-testid attributes or CSS classes
Missing teardown on failureTeardown not running after exceptionUse Run Keyword If Test Failed in teardown
Parallel execution conflictsShared state between processesUse pabotlib or isolate test data per process
Log pollutionToo many screenshotsCapture only on failure or for specific steps
FOR loop scope issuesVariables leaking between iterationsUse END and localize loop variables

13. References

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.