Architecture of Robot Framework tests
Introduction
In this article, you can learn the basics of Robot Framework test architecture.
It is assumed that you know the material of the article
«Robot Framework Basics»
The official recommendations for the project structure can be studied
here
Custom Keywords
Let's start by creating our own keywords inside the same file with tests.
robot/ `-- Tests `-- ebay `-- BasicSearch.robot
You can declare your own keywords in the Keywords section.
In this case, the Test Case will be shorter and easier to read.
*** Settings ***
Documentation Basic Search Functionality
Library SeleniumLibrary
*** Variables ***
*** Test Cases ***
Verify basic search functionality for eBay
[Documentation] This test case verifies the basic search
[Tags] Functional
Start TestCase
Verify Search Results
Finish TestCase
*** Keywords ***
Start TestCase
Open Browser https://www.ebay.com chrome
Input Text //*[@id="gh-ac"] mobile
Verify Search Results
Click Element id:gh-btn
Page Should Contain results for mobile
Finish TestCase
Close Browser
robot -d results Tests/eBay/BasicSearch.robot
The -d option specifies the directory in which the log.html , output.xml and report.html
============================================================================== BasicSearch :: Basic Search Functionality ============================================================================== Verify basic search functionality for eBay :: This test case verif... DevTools listening on ws://127.0.0.1:65225/devtools/browser/bf56f09f-36d7-45c1-80a8-88687db70932 Verify basic search functionality for eBay :: This test case verif... | PASS | ------------------------------------------------------------------------------ BasicSearch :: Basic Search Functionality | PASS | 1 test, 1 passed, 0 failed ============================================================================== Output: /home/andrei/robot/Tests/ebay/results/output.xml Log: /home/andrei/robot/Tests/ebay/results/log.html Report: /home/andrei/robot/Tests/ebay/results/report.html
.resource
In modern versions of Robot Framework, files that contain keywords but are not intended to run tests themselves are usually created with the .resource extension
Unlike libraries, a resource cannot be renamed using as when imported.
The discussion about adding this feature is underway in
issue 2104
From the
official documentation
it follows that .resource is now preferable to .robot
Resource files can use the .robot extension as well, but using the dedicated .resource extension is recommended and may be mandated in the future.
Files containing non-ASCII characters must be saved using the UTF-8 encoding.
Move Keywords to separate file
Storing everything in one file quickly becomes inconvenient.
It is recommended to leave the tests themselves in a file with the extension
.robot
, you can leave the original
BasicSearch.robot
and divide Keywords into two groups - general and related to the project.
In Robot Framework, a special extension is used for these purposes
.resource
which you can read about in the
previous paragraph
The project structure with separate resources will look like this original way:
robot/ |-- Resources | |-- CommonFunctionality.resource | `-- eBayUserDefinedKeywords.resource `-- Tests `-- ebay `-- BasicSearch.robot
BasicSearch.robot
*** Settings ***
Documentation Basic Search Functionality
Resource ../../Resources/CommonFunctionality.resource
Resource ../../Resources/eBayUserDefinedKeywords.resource
*** Variables ***
*** Test Cases ***
Verify basic search functionality for eBay
[Documentation] This test case verifies the basic search
[Tags] Functional
Start TestCase
Verify Search Results
Finish TestCase
Please note that in the file BasicSearch.robot you no longer need to include SeleniumLibrary and write Keywords
In the file CommonFunctionality.resource we will take out such common actions as opening the browser, closing the browser, and so on
*** Settings ***
Library SeleniumLibrary
*** Keywords ***
Start TestCase
Open Browser https://www.ebay.com chrome
Maximize Browser Window
Finish TestCase
Close Browser
Pay attention to line 3. Custom keys contain keys from the SeleniumLibrary library, so it needs to be connected in the settings.
In the file eBayUserDefinedKeywords.resource we will put everything that relates specifically to this project
*** Settings ***
Library SeleniumLibrary
*** Keywords ***
Verify Search Results
Input Text //*[@id="gh-ac"] mobile
Click Element id:gh-btn
Page Should Contain results for mobile
Filter Results By Condition
Mouse Over //*[@id="w7"]
Sleep 3s
Mouse Down //*[@id="w7"]/div/ul/li[2]
Click Element //*[@id="w7"]/div/ul/li[2]
Verify Filter Results
Element Should Contain //*[@id="srp-river-results-query_answer1-w0-x-carous
robot -d results Tests/eBay/BasicSearch.robot
============================================================================== BasicSearch :: Basic Search Functionality ============================================================================== Verify basic search functionality for eBay :: This test case verif... | PASS | ------------------------------------------------------------------------------ BasicSearch :: Basic Search Functionality | PASS | 1 test, 1 passed, 0 failed ==============================================================================
If you get an error No keyword with name 'Start TestCase' found
============================================================================== BasicSearch :: Basic Search Functionality ============================================================================== Verify basic search functionality for eBay :: This test case verif... |FAIL | No keyword with name 'Start TestCase' found. ------------------------------------------------------------------------------ BasicSearch :: Basic Search Functionality |FAIL | 1 test, 0 passed, 1 failed ==============================================================================
- make sure that at the beginning BasicSearch.robot you specified the correct path to the files using Resourse CommonFunctionality.resource , eBayUserDefinedKeywords.resource
*** Settings ***
Documentation Basic Search Functionality
Resource ../../Resources/CommonFunctionality.resource
Resource ../../Resources/eBayUserDefinedKeywords.resource
Test Setup and Test Teardown
The code from the previous example will work fine if successful.
However, if the result is FAIL, the browser will not close automatically.
To save yourself the trouble of cleaning up the environment in case of failure, use
Test Setup and Test Teardown
*** Settings ***
Documentation Basic Search Functionality
Resource ../../Resources/CommonFunctionality.robot
Resource ../../Resources/eBayUserDefinedKeywords.robot
Test Setup Start TestCase
Test Teardown Finish TestCase
*** Variables ***
*** Test Cases ***
Verify basic search functionality for eBay
[Documentation] This test case verifies the basic search
[Tags] Functional
Verify Search Results
Filter Results By Condition
Verify Filter Results
Explicitly specify the source of the keyword
If user keys are repeated in different files, a conflict is possible.
To avoid this, you can explicitly specify the source of your Keyword.
eBayUserDefinedKeywords.Verify Search Results
eBayUserDefinedKeywords.Filter Results By Condition
eBayUserDefinedKeywords.Verify Filter Results
Include your Python library
Basics
Robot Framework allows you to do a lot of complex tests without going beyond the .robot files.
However, I am one of those RF users who prefer to shift the main load
to Python libraries, and keep .robot files as simple as possible.
Libraries are usually stored in the lib, libraries, lib, Libraries, and similar directories. You can import
by specifying a relative path.
In my experience, in
Linux
systems, you don't need to specify .py after the library. I will do this first for clarity and
compatibility.
*** Settings *** Library ../libraries/app.py
If the library has a function some_name(), then it should be called from the robot without brackets, replacing the underscore with a space and making the first letters of words capital - that is, like Some Name
Simple example
Let's look at a simple example: a Python library issues one or another url. Robot will check the title.
In the part
the test runs
will be PASS, in the part FAIL
ext_py_lib/ |-- browser |-- libraries | `-- unstable_url.py `-- tests `-- test_title.robot
from random import randrange def get_unstable_url() -> str: if randrange(2) == 1: return "https://www.urn.su" else: return "https://www.heihei.ru"
*** Settings *** Documentation Example that opens single page Library Browser ... enable_playwright_debug=${True} ... auto_closing_level=TEST ... retry_assertions_for=0:00:03 Library ../libraries/unstable_url.py Force Tags ui *** Variables *** *** Keywords *** Test Setup Tasks Start Chromium Browser Test Teardown Tasks Close Browser Start Chromium Browser New Browser browser=chromium headless=True New Context viewport={'width': 1920, 'height': 1080} ignoreHTTPSErrors=True *** Test Cases *** Starting a browser with a page [Tags] title ${url} = Get Unstable Url New Page ${url} Get Title == URN.SU Close Browser
robot tests
============================================================================== Tests ============================================================================== Tests.Test Title :: Example that opens single page ============================================================================== Starting a browser with a page | PASS | ------------------------------------------------------------------------------ Tests.Test Title :: Example that opens single page | PASS | 1 test, 1 passed, 0 failed ============================================================================== Tests | PASS | 1 test, 1 passed, 0 failed ============================================================================== Output: C:\Users\Andrei\robot\ext_py_lib\output.xml Log: C:\Users\Andrei\robot\ext_py_lib\log.html Report: C:\Users\Andrei\robot\ext_py_lib\report.html
robot tests
============================================================================== Tests ============================================================================== Tests.Test Title :: Example that opens single page ============================================================================== Starting a browser with a page | FAIL | Title 'HeiHei.ru' (str) should be 'URN.SU' (str) ------------------------------------------------------------------------------ Tests.Test Title :: Example that opens single page | FAIL | 1 test, 0 passed, 1 failed ============================================================================== Tests | FAIL | 1 test, 0 passed, 1 failed ============================================================================== Output: C:\Users\Andrei\robot\ext_py_lib\output.xml Log: C:\Users\Andrei\robot\ext_py_lib\log.html Report: C:\Users\Andrei\robot\ext_py_lib\report.html
For information on how to add the ability to write to the robot log and/or console for Python functions, read here
Path to libraries
In the previous example, the libraries were in the libraries directory and the tests were in tests so the library import looked like this original way
Library ../libraries/unstable_url.py
If subdirectories appear in the tests directory, the import from there will look like
Library ../../libraries/unstable_url.py
or even like this
Library ../../../libraries/unstable_url.py
To avoid relative import, you can use one of the methods described below
--pythonpath
Using the --pythonpath option, you can temporarily add the path to the libraries to
PYTHONPATH
Starting with this example, we will specify the libraries without .py
Library unstable_url
robot --pythonpath /c/Users/Andrei/robot/ext_py_lib/libraries test_unstable_title.robot
--argumentfile
To avoid entering the path manually, you can save it in the so-called argumentfile
Let's create a file
all_arguments.robot
and add the following code there
--pythonpath /c/Users/Andrei/robot/ext_py_lib/libraries test_unstable_title.robot
To use this file, we will use the --argumentfile option.
robot --argumentfile all_arguments.robot test_unstable_title.robot
Dockerfile
If your environment is created using
Docker
,
then the path to the libraries can be specified in
Dockerfile
An example that works in one of my projects:
… ENV TEST_DIR=/opt ENV PYTHON_DIR=/user/local/bin/python ENV ROBOT_RESOURCES=/opt/robot/src/resources ENV ROBOT_LIBRARIES=/opt/robot/src/libraries ENV PYTHONPATH=$TEST_DIR:$PYTHON_DIR:$ROBOT_RESOURCES:$ROBOT_LIBRARIES …
More complex example
Example of testing Desktop application using the library PyWinAuto you can study here
| Robot Framework | |
| Architecture | |
| Logs | |
| __init__.robot | |
| Create custom .py libs | |
| Path to libs and resources | |
| Keyword as decorator | |
| Template | |
| Parametrize | |
| Demo with pywinauto |