# Robot Framework

`wopee_rf` adds visual testing to your Robot Framework tests. Your test takes a screenshot at the steps you choose, Wopee.io compares it with the approved baseline, and you review the differences in [Commander](<https://cmd.wopee.io>).

You can use it in two ways:

1. **Keywords**: add `Start Suite`, `Start Scenario`, `Track Fullpage` and `Stop Scenario` to your tests. You decide where screenshots are taken and how steps are named. This page uses this way.
2. **Listener**: run your existing tests unchanged with `--listener wopee_rf.Listener` and track a screenshot after selected keywords. See [Configuration and listener › Listener](<https://docs.wopee.io/robot-framework/02-manual-setup/#listener>).

Both work with the [Browser library](<https://robotframework-browser.org>) and SeleniumLibrary. The `Track` keyword compares any image you pass in, for example from Appium or a PDF rendered to PNG ([examples](<https://docs.wopee.io/robot-framework/04-some-more-examples/index.md>)).

This page walks through a complete example on [Sauce Demo](<https://www.saucedemo.com>): two screenshots, a first run that creates the baselines, and a second run that catches a visual bug. Verified with `wopee_rf` 2.7.2, Robot Framework 7.5 and robotframework-browser 21.0.

Created the project in Commander? It already has a Robot Framework repository with a ready test: see [Template project](<https://docs.wopee.io/robot-framework/03-setup-with-make/index.md>).

## Prerequisites

- Python 3.11 or newer
- Robot Framework 7 or newer
- Node.js 22 or newer, for the Browser library
- A Wopee.io account in [Commander](<https://cmd.wopee.io>)

## 1\. Create a project

1. In Commander, click **NEW PROJECT** and paste the **App URL** (for example `https://www.saucedemo.com`).
2. Open **Advanced settings** and set **Test framework** to **Robot Framework**. **Explore the app and generate tests** switches off, because test generation is available for Playwright only.
3. Click **Create project**.

## 2\. Get the API key

In the project, open **More › Settings › API Keys**. The page shows `WOPEE_API_URL` and `WOPEE_PROJECT_UUID`. Enter a name and click **Generate a new key**. The key is shown only once: copy it right away.

## 3\. Install

```shell
python3 -m venv .venv
source .venv/bin/activate          # Windows PowerShell: .venv\Scripts\Activate.ps1

pip install "wopee_rf>=2.7.2" robotframework robotframework-browser
rfbrowser init chromium
```

## 4\. Configure

Create a `.env` file next to your tests folder. Copy the first three values from **API Keys**:

```text
WOPEE_API_URL=https://api.wopee.io
WOPEE_PROJECT_UUID=your-project-uuid
WOPEE_API_KEY=your-api-key
WOPEE_SCREENSHOT_VALIDATION_ENABLED=true
WOPEE_DRIVER_LIBRARY=BrowserLibrary
```

> [!WARNING]
>
> **Both last lines are required**
>
> Without `WOPEE_SCREENSHOT_VALIDATION_ENABLED=true` the keywords send nothing. Without `WOPEE_DRIVER_LIBRARY` the library cannot take screenshots. In both cases `Track Fullpage` returns `None`. The test below then fails on `${login.status}` with `'NoneType' object has no attribute 'status'`, but a test that does not read the result passes, and nothing tells you that no screenshot reached Wopee.io. Use `SeleniumLibrary` instead of `BrowserLibrary` for Selenium tests.

Keep `.env` out of version control. In CI, set the same variables as environment variables or secrets instead.

## 5\. Write the test

`tests/saucedemo.robot`:

```robotframework
*** Settings ***
Library     Browser
Library     wopee_rf.Standalone    dot_env_path=.env

Test Setup       New Page    https://www.saucedemo.com
Test Teardown    Stop Scenario


*** Variables ***
${USER}     standard_user
${SUITE}    Robot Framework demo ${{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}}


*** Test Cases ***
Login And Products
    Start Suite       suite_name=${SUITE}
    Start Scenario    scenario_name=Robot Framework: login and products

    ${login}=    Track Fullpage    step_name=Login page

    Fill Text    id=user-name    ${USER}
    Fill Text    id=password     secret_sauce
    Click        id=login-button
    Wait For Elements State    css=.inventory_list    visible

    ${products}=    Track Fullpage    step_name=Products

    Log To Console    \nLogin page: ${login.status} | Products: ${products.status}
```

- `Start Suite` starts a run in Commander. A suite with the same name on the same branch is reused, so the timestamp gives every run its own entry.
- `Start Scenario` groups the screenshots of one test.
- `Track Fullpage` takes a full-page screenshot and returns the result with `status` and `image_url`.
- `Stop Scenario` in the teardown finishes the scenario even when the test fails.
- All Wopee.io keywords take named arguments only: write `step_name=Login page`, not just `Login page`.

## 6\. First run: create the baselines

Run `robot` from the folder that holds `.env`, because `dot_env_path` is relative to the working directory:

```shell
robot -d reports tests/
```

```text
Login And Products
Login page: new | Products: new
| PASS |
```

Both steps are `new`: there is no baseline yet. The Robot log (`reports/log.html`) shows the full result of each step, including `image_url`, the link to the step in Commander.

## 7\. Approve in Runs

Open **Runs** in Commander and select the run `Robot Framework demo ...`, then each step, and click **Approve**. The screenshot becomes the baseline.

The screenshots on this page come from the Playwright demo; a Robot Framework run looks the same.

## 8\. Second run: catch a visual bug

Sauce Demo has a `visual_user` whose products page is visually broken. Run the same test as that user:

```shell
robot -d reports -v USER:visual_user tests/
```

```text
Login page: ok | Products: unresolved
```

**Login page** matches the baseline. **Products** is `unresolved`: open it in **Runs**, inspect the highlighted differences and **Reject** it as a bug, or **Approve** it if the change is intended.

## Good to know

- **A difference does not fail the test.** The Robot test still passes and the step waits for review. To fail the test on a difference, add `WOPEE_ENABLE_SOFT_ASSERT=false` to `.env` (see [Fail the test on a visual difference](<https://docs.wopee.io/robot-framework/02-manual-setup/#fail-the-test-on-a-visual-difference>)).
- **Baselines** are identified by `<scenario name>-<step name>` plus the branch and, if set, the viewport. Keep both names stable between runs.
- **Branches**: `WOPEE_BRANCH_NAME` sets the branch of the run (default `master`). See [Branches](<https://docs.wopee.io/robot-framework/02-manual-setup/#branches>) and [Baselines and branches](<https://docs.wopee.io/visual-testing/#baselines-and-branches>).
- **Statuses**: `new`, `ok`, `unresolved`, `autoApproved`. See [How it works](<https://docs.wopee.io/visual-testing/#how-it-works>).
- **Tiny differences**: font smoothing can differ by a few pixels between runs, for example `Difference: 0.004%` on an unchanged page. Reject such a step, and set `WOPEE_PIXEL_TO_PIXEL_DIFF_TOLERANCE=0.1` in `.env` to accept differences up to 0.1 %.
- **Wait for the content** you want to capture before each `Track Fullpage`, as the test does with `Wait For Elements State`. See [Wait for fonts and images before tracking](<https://docs.wopee.io/visual-testing/#wait-for-fonts-and-images-before-tracking>).

## Troubleshooting

The most common problems are a missing `WOPEE_SCREENSHOT_VALIDATION_ENABLED=true` or `WOPEE_DRIVER_LIBRARY` (step 4), and unnamed keyword arguments. The full list is in [Configuration and listener › Troubleshooting](<https://docs.wopee.io/robot-framework/02-manual-setup/#troubleshooting>).

## Next steps

- [Configuration and listener](<https://docs.wopee.io/robot-framework/02-manual-setup/index.md>): all settings, the listener, SeleniumLibrary, branches and CI.
- [Setup with Make](<https://docs.wopee.io/robot-framework/03-setup-with-make/index.md>): start from the template project.
- [Examples](<https://docs.wopee.io/robot-framework/04-some-more-examples/index.md>): extra parameters, viewport screenshots, mobile apps and PDF documents.
