什么是RF
RF是一个基于 Python 的、可扩展的关键字驱动的自动化 验收测试框架、验收测试驱动开发 (ATDD)、 行为驱动开发 (BDD) 和机器人流程自动化 (RPA)。它 可用于分布式、异构环境,其中自动化 需要使用不同的技术和接口。
该框架周围有一个丰富的生态系统,由各种通用 作为单独项目开发的库和工具。查看更多 有关机器人框架和生态系统的信息,请参阅 http://robotframework.org。
为什么使用RF?
- 支持易于使用的表格语法,以便在统一的环境中创建测试用例 道路。
- 提供从 现有关键字。
- 以 HTML 格式提供易于阅读的结果报告和日志。
- 独立于平台和应用程序。
- 提供用于创建自定义测试库的简单库 API 可以使用 Python 本地实现。
- 提供命令行界面和基于 XML 的输出文件 集成到现有的构建基础架构中(持续集成 系统)。
- 为测试 Web 应用程序、rest API、移动应用程序提供支持 运行进程,通过 Telnet 或 SSH 连接到远程系统等。
- 支持创建数据驱动的测试用例。
- 内置对变量的支持,特别适用于测试 不同的环境。
- 提供标记以对要执行的测试用例进行分类和选择。
- 实现与源代码管理的轻松集成:测试套件只是文件 以及可以使用生产代码进行版本控制的目录。
- 提供测试用例和测试套件级别的设置和拆卸。
- 模块化架构支持创建测试,甚至对于具有 几种不同的接口。
环境准备
- 安装python
- 虚拟环境中安装robotframework
cd C:\projects
mkdir MyProject
cd MyProject
python -m venv .venv
.venv\Scripts\activate.bat
pip install robotframework
robot --version
3.pycharm安装插件
Robot Framework Language Server
为 Robot Framework 添加调试配置以运行当前测试套件
添加 Robot Framework 的调试配置以运行当前测试用例(通过选定的文本)
4、安装库文件
pip install --upgrade robotframework-seleniumlibrary
5、下载浏览器驱动,放置python路径的Scripts目录下。
Library
关于射频指南 |机器人框架 (robotframework.org)
使用RF需要使用Library,常用的第三方库如下:
在web浏览器中进行web应用程序测试可以使用的库是
- Selenium Library 在内部使用流行的 Selenium 工具的 Web 测试库
- Browser Library 由 Playwright 提供支持。以速度、可靠性和可见性为目标。
web service和restful API可以用的库是
- Requests Library 一个机器人框架库,旨在通过包装众所周知的 Python 请求库来提供 HTTP API 测试功能
标准库
RF标准库是Robot Framework(RF)在安装完成后自带的库。这些库无需额外安装,可以直接在RF中使用。其中,Builtin库是一个常用关键字库,它包含经常需要使用的关键字,无需导入即可直接使用。除Builtin库外,其他标准库如Dialogs、Collections、OperatingSystem、Remote、Screenshot和Process等,都需要通过import导入才能使用。这些库提供了丰富的功能,例如暂停测试执行和从用户获取输入、处理Python列表和字典、执行各种操作系统相关的任务、远程库接口的支持、捕获和存储桌面截图以及管理系统中运行的过程等。
标准库 |机器人框架 (robotframework.org)
selenium Library
https://robotframework.org/SeleniumLibrary/SeleniumLibrary.html
selenium Library是RF的一个web测试库,内部使用selenium。
pip install --upgrade robotframework-seleniumlibrary
新建一个test.robot文件,robot是RF测试用例文件的后缀。
首先在Settings导入SeleniumLibrary,然后在TestCase里写测试用例,如下例的Open Browser都是SeleniumLibrary提供的关键字,如下用例打开edge浏览器,输入框中输入关键字,并点击百度一下按钮,最后关闭浏览器。
*** Settings ***
Library SeleniumLibrary
*** Test Cases ***
Search keywords in baidu
Open Browser url=https://www.baidu.com browser=edge
Input Text //input[@id="kw"] 周杰伦
Click Element //input[@id="su"]
Sleep 5
Close Browser
导入Library失败
原因是python环境变量错了,电脑上有3.7的和3.8的,我用的3.8的,但是没有把3.8设置为环境变了
输入关键字,会有提示如图Input password,会提示让输入定位和密码。
Browser Library
这个库是由playwright支持的
Browser Library | ROBOT FRAMEWORK
pip install robotframework-browser
rfbrowser init
Installing playwright...
Installing playwright-chromium...
Installing playwright-firefox...
Installing playwright-webkit...
Done!
Requests Library
这个库可以进行API测试,基于Python的Requests
pip install robotframework-requests
*** Settings ***
Library RequestsLibrary
*** Test Cases ***
Quick Get Request Test
${response}= GET https://www.google.com
Quick Get Request With Parameters Test
${response}= GET https://www.google.com/search params=query=ciao expected_status=200
Quick Get A JSON Body Test
${response}= GET https://jsonplaceholder.typicode.com/posts/1
Should Be Equal As Strings 1 ${response.json()}[id]
运行用例
方法一:使用配置的run testsuite按钮。
方法二:
点击在测试文件里左侧的按钮,这里的按钮其实也是插件配置出的按钮。
运行后可以看到测试结果,并生成了html格式的测试报告。
测试报告
项目结构
Test Suites 可以组织在一个或多个robot文件里,可以放在tests/文件夹下
resources 资源文件,里面存放的是可重复使用的keywords,可以是robot文件或py文件,可以放在resources文件夹下,如
common.resource -存放一般的关键字,如Login/Logout,导航
search.robot,跟查询有关的关键字
util.py python相关的关键字
libraries 常用的python关键字库,可以存放在libraries/文件夹下,某些项目会区分libraries和resources,有些不会。
如
my_project
├── tests
│ ├── suiteA.robot
│ ├── suiteB.robot
│ ├── ...
│
├── resources
│ ├── common.resource
│ ├── some_other.resource
│ ├── custom_library.py
│ ├── variables.py
│ ├── ...
│
├── .gitlab-ci.yml
├── .gitignore
├── README.md
├── requirements.txt
执行用例
$ robot --pythonpath . tests
一些项目还会有data文件,存放测试数据
my_project
├── tests
│ ├── authentication
│ │ ├── login.robot
│ │ ├── ...
│ │
│ ├── master-data
│ │ ├── customers.robot
│ │ ├── products.robot
│ │ ├── ...
│ │
│ ├── order
│ │ ├── order_creation.robot
│ │ ├── order_processing.robot
│ │ ├── ...
│
├── resources
│ ├── common.resource
│ ├── search.resource
│ ├── master-data
│ │ ├── customers.resource
│ │ ├── products.resource
│ │ ├── ...
│ │
│ ├── ...
│
├── data
│ ├── master-data
│ │ ├── customers.py
│ │ ├── products.py
│ │ ├── ...
│ │
│ ├── order
│ │ ├── order_creation.yaml
│ │ ├── order_processing.yaml
│ │ ├── ...
│
├── .gitlab-ci.yml
├── .gitignore
├── README.md
├── requirements.txt
示例 项目
RF官网提供了几个例子
Examples Overview | ROBOT FRAMEWORK
Vehicle Insurance App
根据下面的例子可以看到,RF的测试文件,包含
*** Settings ***-用来引入库和资源
*** Variables *** 用来指定变量,在测试用例中可使用${}来引用。
*** Test Cases *** 下面为用例,其中用例Create Quote for Car下包含的关键字,都是在*** Keywords ***中自定义的。
*** Keywords *** 定义关键字,关键字下调用Browser库文件中的关键字
-
[Arguments] firstname=Max{lastname}=Mustermann
- 这行定义了这个关键字需要的参数及其默认值。在这个例子中,
Enter Insurant Data
关键字接受两个参数:firstname
和lastname
。如果调用这个关键字时没有提供这些参数的值,那么它们将分别默认为Max
和Mustermann
。
- 这行定义了这个关键字需要的参数及其默认值。在这个例子中,
*** Settings ***
Library Browser
*** Variables ***
${BROWSER} chromium
${HEADLESS} false
*** Test Cases ***
Create Quote for Car
Open Insurance Application
Enter Vehicle Data for Automobile
Enter Insurant Data
Enter Product Data
Select Price Option
Send Quote
End Test
*** Keywords ***
Open Insurance Application
New Browser browser=${BROWSER} headless=${HEADLESS}
New Context locale=en-GB
New Page http://sampleapp.tricentis.com/
Enter Vehicle Data for Automobile
Click div.main-navigation >> "Automobile"
Select Options By id=make text Audi
Fill Text id=engineperformance 110
Fill Text id=dateofmanufacture 06/12/1980
Select Options By id=numberofseats text 5
Select Options By id=fuel text Petrol
Fill Text id=listprice 30000
Fill Text id=licenseplatenumber DMK1234
Fill Text id=annualmileage 10000
Click section[style="display: block;"] >> text=Next »
Enter Insurant Data
[Arguments] ${firstname}=Max ${lastname}=Mustermann
Fill Text id=firstname Max
Fill Text id=lastname Mustermann
Fill Text id=birthdate 01/31/1980
Check Checkbox *css=label >> id=gendermale
Fill Text id=streetaddress Test Street
Select Options By id=country text Germany
Fill Text id=zipcode 40123
Fill Text id=city Essen
Select Options By id=occupation text Employee
Click text=Cliff Diving
Click section[style="display: block;"] >> text=Next »
Enter Product Data
Fill Text id=startdate 06/01/2023
Select Options By id=insurancesum text 7.000.000,00
Select Options By id=meritrating text Bonus 1
Select Options By id=damageinsurance text No Coverage
Check Checkbox *css=label >> id=EuroProtection
Select Options By id=courtesycar text Yes
Click section[style="display: block;"] >> text=Next »
Select Price Option
[Arguments] ${price_option}=Silver
Click *css=label >> css=[value=${price_option}]
Click section[style="display: block;"] >> text=Next »
Send Quote
Fill Text "E-Mail" >> .. >> input max.mustermann@example.com
Fill Text "Phone" >> .. >> input 0049201123456
Fill Text "Username" >> .. >> input max.mustermann
Fill Text "Password" >> .. >> input SecretPassword123!
Fill Text "Confirm Password" >> .. >> input SecretPassword123!
Fill Text "Comments" >> .. >> textarea Some comments
${promise}= Promise To Wait For Response matcher=http://sampleapp.tricentis.com/101/tcpdf/pdfs/quote.php timeout=10
Click "« Send »"
${body}= Wait For ${promise}
Log ${body}[status]
Log ${body}[body]
Wait For Elements State "Sending e-mail success!"
Click "OK"
End Test
Close Context
Close Browser
WFA login
这个例子中引用了py文件中的函数
另外在Settings里可以使用Suite Setup和Suite Teardown进行test suite级别的测试数据准备和清理
Test Setup和Suite Teardown进行test级别前置和后置准备。
*** Settings ***
Library Browser
Library totp.py
Suite Setup New Browser browser=${BROWSER} headless=${HEADLESS}
Test Setup New Context
Test Teardown Close Context
Suite Teardown Close Browser
*** Variables ***
${BROWSER} chromium
${HEADLESS} False
*** Test Cases ***
Login with MFA
New Page https://seleniumbase.io/realworld/login
Fill Text id=username demo_user
Fill Text id=password secret_pass
${totp} Get Totp GAXG2MTEOR3DMMDG
Fill Text id=totpcode ${totp}
Click "Sign in"
Get Text h1 == Welcome!
import pyotp
def get_totp(secret):
totp = pyotp.TOTP(secret)
return totp.now()
Restful Booker
*** Settings ***
Library RequestsLibrary
Library Collections
Suite Setup Authenticate as Admin
*** Test Cases ***
Get Bookings from Restful Booker
${body} Create Dictionary firstname=John
${response} GET https://restful-booker.herokuapp.com/booking ${body}
Status Should Be 200
Log List ${response.json()}
FOR ${booking} IN @{response.json()}
${response} GET https://restful-booker.herokuapp.com/booking/${booking}[bookingid]
TRY
Log ${response.json()}
EXCEPT
Log Cannot retrieve JSON due to invalid data
END
END
Create a Booking at Restful Booker
${booking_dates} Create Dictionary checkin=2022-12-31 checkout=2023-01-01
${body} Create Dictionary firstname=Hans lastname=Gruber totalprice=200 depositpaid=false bookingdates=${booking_dates}
${response} POST url=https://restful-booker.herokuapp.com/booking json=${body}
${id} Set Variable ${response.json()}[bookingid]
Set Suite Variable ${id}
${response} GET https://restful-booker.herokuapp.com/booking/${id}
Log ${response.json()}
Should Be Equal ${response.json()}[lastname] Gruber
Should Be Equal ${response.json()}[firstname] Hans
Should Be Equal As Numbers ${response.json()}[totalprice] 200
Dictionary Should Contain Value ${response.json()} Gruber
Delete Booking
${header} Create Dictionary Cookie=token\=${token}
${response} DELETE url=https://restful-booker.herokuapp.com/booking/${id} headers=${header}
Status Should Be 201 ${response}
*** Keywords ***
Authenticate as Admin
${body} Create Dictionary username=admin password=password123
${response} POST url=https://restful-booker.herokuapp.com/auth json=${body}
Log ${response.json()}
${token} Set Variable ${response.json()}[token]
Log ${token}
Set Suite Variable ${token}
todo MVC
这是一个BDD的例子
*** Settings ***
Library Browser
Library String
Suite Setup New Browser browser=${BROWSER} headless=${HEADLESS}
Test Setup New Context viewport={'width': 1920, 'height': 1080}
Test Teardown Close Context
Suite Teardown Close Browser
*** Variables ***
${BROWSER} chromium
${HEADLESS} False
*** Test Cases ***
Add Two ToDos And Check Items
[Documentation] Checks if ToDos can be added and ToDo count increases
[Tags] Add ToDo
Given ToDo App is open
When I Add A New ToDo "Learn Robot Framework"
And I Add A New ToDo "Write Test Cases"
Then Open ToDos should show "2 items left"
Add Two ToDos And Check Wrong Number Of Items
[Documentation] Checks if ToDos can be added and ToDo count increases
[Tags] Add ToDo
Given ToDo App is open
When I Add A New ToDo "Learn Robot Framework"
And I Add A New ToDo "Write Test Cases"
Then Open ToDos should show "1 items left"
Add ToDo And Mark Same ToDo
[Tags] Mark ToDo
Given ToDo App is open
When I Add A New ToDo "Learn Robot Framework"
And I Mark ToDo "Learn Robot Framework"
Then Open ToDos should show "0 items left"
Check If Marked ToDos are removed
Given ToDo App is open
And I Added Two ToDos
When I Mark One ToDo
Then Open ToDos should show "1 item left"
Split ToDos
Given ToDo App is open
When I Add New ToDos "Learn Robot Framework&Write Test Cases&Sleep"
Then Open ToDos should show "3 items left"
Add A Lot Of Todos
Given ToDo App is open
When I Add "100" ToDos
Then Open ToDos should show "100 items left"
Add A Lot Of Todos With WHILE
Given ToDo App is open
When I Add "100" ToDos With WHILE Loop
Then Open ToDos should show "100 items left"
*** Keywords ***
ToDo App is open
New Page https://todomvc.com/examples/react/
I Add A New ToDo "${todo}"
Fill Text .new-todo ${todo}
Press Keys .new-todo Enter
I Add New ToDos "${todo}"
IF "&" in $todo
@{todos} Split String ${todo} separator=&
FOR ${item} IN @{todos}
Fill Text .new-todo ${item}
Press Keys .new-todo Enter
END
ELSE
Fill Text .new-todo ${todo}
Press Keys .new-todo Enter
END
Open ToDos should show "${text}"
Get Text span.todo-count == ${text}
I Mark ToDo "${todo}"
Click "${todo}" >> .. >> input.toggle
I Added Two ToDos
I Add A New ToDo "Learn Robot Framework"
I Add A New ToDo "Write Test Cases"
I Mark One ToDo
Click li:first-child >> input.toggle
I Add "${count}" ToDos
FOR ${index} IN RANGE ${count}
I Add A New ToDo "My ToDo Number ${index}"
END
I Add "${count}" ToDos With WHILE Loop
${x}= Set Variable ${0}
WHILE ${x} < ${count}
${x}= Evaluate ${x} + 1
I Add A New ToDo "My ToDo Number ${x}"
END
风格指南
风格指南 |机器人框架 (robotframework.org)
Sections
*** Comments ***
*** Settings ***
*** Variables ***
*** Test Cases ***
*** Keywords ***
Settings
*** Settings ***
Documentation
Metadata
Library BuiltIn
Library 3rd Party
Library Custom
Resource
Variables
Suite Setup
Suite Teardown
Test Setup
Test Teardown
Test Template
Test Timeout
Test Tags
Variables
*** Variables ***
${VARIABLE} This is a Variable
${COMPOSITE VARIABLES} ${VARIABLE} with other variables.
Test Cases
Test Case
[Documentation]
[Tags]
[Timeout]
[Setup]
[Template]
Static Variable Assignments
Keyword Calls
Verification Keyword Call
[Teardown]
Keyword
Keyword
[Documentation]
[Tags]
[Arguments]
[Timeout]
[Setup]
Static Variable Assignments
Keyword Calls
[Teardown]
扩展RF
可以写Python库
Static Library
静态库中RF的关键字被定义为python的方法。
Static Library With a Class
class DemoLibrary:
def __init__(self, *args, **kwargs):
print(f"Sample Library initialized with args: {args} and kwargs: {kwargs}")
def my_keyword(self, *args, **kwargs):
print(f"Keyword got args: {args} and kwargs: {kwargs}")
return "Hello World"
*** Settings ***
Library DemoLibrary.py
*** Test Cases ***
Use a Keyword with multiple arguments
My Keyword Argument 1 Argument 2 Named Argument=One Value
Static Library withouth a Class
将关键字定义在python方法中
import base64
def encode_as_base64(string):
"""
Encode string as base64.
"""
return base64.b64encode(string.encode())
def decode_from_base64(string):
"""
Decode string from base64.
"""
return base64.b64decode(string).decode()
*** Settings ***
Library LibraryWithoutClass.py
*** Test Cases ***
Use Custom Keywords
${base64} Encode As Base64 This is a Test String
Log ${base64}
${decoded} Decode From Base64 ${base64}
Log ${decoded}
Decorators
可以使用装饰@@keyword和@not_keyword将方法装饰为关键字。
from robot.api.deco import keyword, not_keyword
@keyword('Login via user panel')
def login(username, password):
# ...
@not_keyword
def this_is_not_keyword():
pass
from robot.api.deco import keyword
@keyword(tags=['tag1', 'tag2'])
def login(username, password):
# ...
@keyword('Custom name', ['tags', 'here'])
def another_example():
# ...
@keyword(types={'count': int, 'case_insensitive': bool})
def example_keyword(count, case_insensitive=True):
if case_insensitive:
# ...
@keyword(types=[int, bool])
def example_keyword(count, case_insensitive=True):
if case_insensitive:
# ...
BDD
BDD (Behavior Driven Development) | ROBOT FRAMEWORK
变量
*** Variables *** Section
定义在这个部分的变量可以用于同一个文件中的所有的test cases和关键字中。
定义在这个部分的变量是suite变量。
如果一个resource或者robot文件中有variables部分被导入到test suite中,则这些变量也成为suite变量。
*** Variables ***
${my_var} my_value
@{my_list} Apple Banana Orange
&{my_dict} name=my_value1 password=my_value2
*** Test Cases ***
Test Case 1
Log ${my_var}
Log ${my_list}
Log ${my_dict}
FOR ${item} IN @{my_list}
Log ${item}
END
Log ${my_dict}[name]
Log ${my_dict}[password]
FOR ${key} ${value} IN &{my_dict}
Log Many ${key} ${value}
END
My Keyword
*** Keywords ***
My Keyword
Log Many ${my_var} ${my_list} ${my_dict}
在测试用例和关键字中设置变量
除了 *** 变量 *** 部分,还可以在测试用例和关键字中动态设置变量。 变量由关键字的返回值设置。 有一些关键字显式设置变量值,例如
- 设置变量
- 设置测试变量
- 设置套件变量
- 设置全局变量
它们可用于设置变量的值或更改变量的范围。
变量有不同的级别。
*** Test Cases ***
Test Case 1
${my_local_var} Set Variable Hello World #用例级别的变量
Log ${my_local_var} # Pass: Logs the value of the variable
Set Suite Variable ${my_suite_var} I'm a suite variable #套件级别变量
Set Global Variable ${my_global_var} I'm a global variable #全局变量
Test Case 2
Log ${my_local_var} # Fails: 这个变量的范围仅存在Test Case1中
Log ${my_suite_var} # Pass: Variable exists for the scope of the whole suite
Log ${my_global_var} # Pass: Variable exists for the scope of the whole test run
Test Case 3
My Keyword
Log ${my_keyword_var} # Fails: 变量的范围为关键字My Keyword中
Log ${my_test_var} # Pass: Variable exists in the scope of the test case
*** Keywords ***
My Keyword
${my_keyword_var} Set Variable Hello Keyword
Log ${my_keyword_var} # Pass: Logs the value of the variable
Set Test Variable ${my_test_var} I'm a test case variable
何时使用 $ 和 @ 以及 & 和 %?
变量名称包括
- 变量类型标识符(例如 、 、 、
$
@
&
%
) - 大括号
{}
- 变量名称(例如 , , ,
my_var
my_list
my_dict
my_var2
)
变量类型标识符用于定义变量的类型。
$
用于标量变量。@
用于列表变量。&
用于字典变量。%
用于环境变量。
标量变量、列表变量和字典有什么区别?
标量变量只能包含一个值。
一个列表变量可以包含多个值。
一个字典变量可以包含多个键值对。
但是,为什么我们可以用语法${my_list}
和语法@{my_list}
来访问列表变量呢?my_list
${my_list}
访问整个 List 对象。它是一个容器,包含列表中的所有项目。 您可以使用它来访问整个列表变量,或者使用语法 访问列表的特定项。my_list
my_list
${my_list}[index]
@{my_list}
访问 list 变量 的项。这就像列表变量被解压缩,所有项目都可以作为单独的变量使用。my_list
my_list
*** Settings ***
Library Collections
*** Variables ***
@{my_list} Apple Banana Orange
*** Test Cases ***
Test Case 1
Log ${my_list} # Pass: 打印整个列表对象 ['Apple', 'Banana', 'Orange']
Log Many @{my_list} # Pass: Logs the items of the list object 分别返回Apple Banana Orange
Log Many ${my_list} # Pass: 打印整个列表对象
Log List ${my_list} # Pass: 打印整个列表对象
Log ${my_list}[0] # Pass: 打印列表对象的第一个元素
Log @{my_list}[0] # Fail: @{my_list} 不是列表对象,不存在index
Log @{my_list} # Fail: The second argument of the Log keyword `level` only allows the values `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `NONE`.
# The value `Banana` for the argument `level` is not allowed.
Log ${my_list}[0] ${my_list}[1] ${my_list}[2] # Fail: Same as above
FOR ${item} IN @{my_list} # Pass: Iterates over the items of the list object
Log ${item} # Pass: 返回列表对象的元素
END
每当您想要访问列表变量的容器时,都必须使用语法${my_list}
。
当您要将列表变量分解为其项时,您必须使用语法@{my_list}
.
这就像一个装有瓶子的啤酒箱。
使用${beer_crate}
该语法,您可以访问整个啤酒箱。
使用语法@{beer_crate}
,您可以得到瓶子。
使用语法[index]
,您可以在板条箱内获得一个特定的瓶子。${beer_crate}
变量文件
可以从外部文件加载变量,如 Python的py或yaml文件。
对于 Yaml 文件,pyyaml是必需的。
pip install pyyaml
可以在py文件中创建简单的变量、列表或字典,甚至是复杂的对象,如类。
PythonVariables.py
class TestEnv:
ip = '123.4.5.6'
user = 'robot'
roles = ['admin', 'user']
my_var = 'Hello World'
my_list = ["Apple", "Banana", "Cherry"]
my_dict = {'name': 'John', 'age': 36}
DynamicVariables.py
import os
import random
import time
import math
USER = os.getlogin() # current login name
RANDOM_INT = random.randint(0, 10) # random integer in range [0,10]
CURRENT_TIME = time.asctime() # timestamp like 'Thu Apr 6 12:45:21 2006'
if time.localtime()[3] > 12:
AFTERNOON = True
else:
AFTERNOON = False
def get_area(diameter):
radius = diameter / 2
area = math.pi * radius * radius
return area
AREA1 = get_area(1)
AREA2 = get_area(2)
.yaml或.yml文件解释为字典
YamlVariables.yml
# These are scalars:
base_url: https://qaserver.mycompany.com:8080
admin_user: iAmAdMiN
admin_password: eieioscoobydoo1234
# Now, a list:
yaml_list:
- Item 1
- Item two
- 3
# Finally, a dictionary:
yaml_dict:
key_1: A string
key_2: 1 # an int
*** Settings ***
Variables PythonVariables.py
Variables YamlVariables.yaml
Variables DynamicVariables.py
*** Test Cases ***
Access Python Variables
Log ${TestEnv.ip}
Log ${TestEnv.roles}
Log Many @{TestEnv.roles}
Log ${my_var}
Log Many @{my_list}
Log Many &{my_dict}
FOR ${item} IN @{my_list}
Log ${item}
END
Access Yaml Variables
Log ${base_url}
Log Many @{yaml_list}
Log ${yaml_dict}
Log ${yaml_dict}[key_1]
Access Dynamic Variables
Log ${USER}
Log ${RANDOM_INT}
Log ${CURRENT_TIME}
Log ${AFTERNOON}
Log ${AREA1}
Log ${AREA2}