变量形式
- 单值变量scalar: ${key}=value
- 列表变量list:@{key}=[1,2,3,'a','b','c']
- 字典变量dict:&{key}={'name': 'robot', 'password': 'secret'}
scalar变量
${scalar}
scalar变量几乎贯穿于整个rf工作空间,其使用频率远远高于list和dict变量,任何list和dict变量均可转换为scalar变量,即scalar变量可以接收list或dict变量;但scalar变量几乎无法转换为list和dict变量。
${scalar} Set Variable robotFramework
log ${scalar}
log ${scalar[2]}
log ${scalar[0:5]}
log ${scalar[5:]}
${list} Set Variable abc 123
log ${list}
${dict} Create Dictionary usename=miker age=32
log ${dict}
* INFO : ${scalar} = robotFramework
* INFO : robotFramework
* INFO : b
* INFO : robot
* INFO : Framework
* INFO : ${list} = [u'abc', u'123']
* INFO : [u'abc', u'123']
* ${dict} = {u'usename': u'miker', u'age': u'32'}
* {u'usename': u'miker', u'age': u'32'}
list变量
@{list}
一维list
@{list} Set Variable Tom Jack May
Log Many @{list}
log ${list}
log @{list}[1]
log ${list}[2]
log ${list[0]}
* INFO : @{list} = [ Tom | Jack | May ]
* INFO : Tom
* INFO : Jack
* INFO : May
* INFO : [u'Tom', u'Jack', u'May']
* INFO : Jack
* INFO : May
* INFO : Tom
多维list
@{listA} Create List 1 2 3
@{listB} Create List 4 5 6
@{listC} Create List ${listA} ${listB} 7
log @{listC}[1][2]
log ${listC[1]}[2]
log ${listC[0][1]}
@{listD} Create List @{listA} @{listB} 7
log ${listD}
* INFO : @{listA} = [ 1 | 2 | 3 ]
* INFO : @{listB} = [ 4 | 5 | 6 ]
* INFO : @{listC} = [ [u'1', u'2', u'3'] | [u'4', u'5', u'6'] | 7 ]
* INFO : [u'4', u'5', u'6'][2]
* INFO : 6
* INFO : 2
* INFO : @{listD} = [ 1 | 2 | 3 | 4 | 5 | 6 | 7 ]
* INFO : [u'1', u'2', u'3', u'4', u'5', u'6', u'7']
rf支持直接用list变量一次性传递多个参数的,调用关键字传入对应参数时需特别注意关键字接收的变量类型,否则会引发参数对应错误。
rf中关键字定义&描述中,有特别标识参数的类型,如下:
Name: Set Variable
Source: BuiltIn <test library>
Arguments: [ *values ]
Name: Should Be Equal
Source: BuiltIn <test library>
Arguments: [ first | second | msg=msg | values=ignore_case | ignore_case=values ]
其中,参数名前带有星号*的为list类型变量,反之为scalar类型变量。
因此在进行Should Be Equal关键字使用时要么依次传入对应的scalar类型变量,要么传入对应长度的list变量,若传入list变量长度不符合关键字入参长度时则会调用关键字失败;同理,当变量使用混乱时,也会导致失败。如下:
@{list} Set Variable Tom Jack May
Should Be Equal @{list} @{list}[0]
* INFO : @{list} = [ Tom | Jack | May ]
* FAIL : May: Tom != Tom
dict变量
&{dict}
rf支持字典变量,字典中的项可以作为命名参数传给关键字。
eg1:
&{dict} Create Dictionary name=tom age=23 21=222 ${22}=33
Log Many &{dict}
log ${dict}
log &{dict}[name]
log ${dict.age}
log ${dict}[21]
log &{dict}[${22}]
log &{dict}
log ${dict.${21}}
* INFO : &{dict} = { name=tom | age=23 | 21=222 | 22=33 }
* INFO : name=tom
* INFO : age=23
* INFO : 21=222
* INFO : 22=33
* INFO : {u'name': u'tom', u'age': u'23', u'21': u'222', 22: u'33'}
* INFO : tom
* INFO : 23
* INFO : 222
* INFO : 33
eg2:eg3:
元组变量
${tuple}
rf还支持元组变量,元组变量与list变量很相似,唯一不同点为元组变量无法修改
${tuple} Set Variable ${1,2}
log ${tuple}
log ${tuple[0]}
log ${tuple}[1]
* INFO : ${tuple} = (1, 2)
* INFO : (1, 2)
* INFO : 1
* INFO : 2
创建变量
rf有5中创建变量方式,分别为:
- 关键字创建/赋值
- 测试类创建变量
- 测试类引入文件变量
- 命令行-v --variable name:value * 传入变量
- 命令行-V --variablefile path * 传入文件变量
关键字创建/赋值
Set Variable: 主要用于设置scalar变量,也可用于设置list变量
Set Variable If: 通过逻辑判断设置变量,${var1}= Set Variable If ${rc}==0 zero nonzero
Set Suite Variable: 设置测试类变量,仅测试类可用
Set Global Variable: 设置全局变量
Set Test Variable: 设置测试用例变量,仅当前测试用例内部可用
Create Dictionary: 创建字典变量
Create List: 创建列表变量
Get Text: 获取text并返回赋值
......
${a} Set Variable hello
${b} Set Variable If 1==1 true false
${c} Set Suite Variable suite
${d} Set Global Variable global
${e} Set Test Variable test
${f} Create Dictionary name=miker
${g} Create List chengdu china
${h} Get Length ${g}
测试类创建变量
测试类引入文件变量
文件内容:
# 观澜互联网外调
devOuterApp = {
"client_id": "P_dev-pussy",
"client_secret": "ye6Q8d6J"
}
引用方式:
${devOuterApp.get("client_id")}
命令行-v --variable name:value * 传入变量
变量可以在命令行中通过选项-v --variable 单个设置,通过命令行设置的变量对所有执行的测试文件是全局可见的, 不过如果局部的变量表格或者局部导入的变量文件中存在重名的变量, 则这些变量也会被命令行中指定的值所覆盖。
设置单个变量的选项格式是 --variable name:value, 其中 name 是变量名, 不带 ${} ,value是变量的值。有多个变量的话就使用这个选项多次。这种方式只能定义scalar变量,很多特殊字符必须使用 -E --escape what:with * 经过转义才能表示。
--variable EXAMPLE:value
--variable HOST:localhost:7272 --variable USER:robot
--variable ESCAPED:Qquotes_and_spacesQ --escape quot:Q --escape space:_
在上例中, 变量值分别是:
${EXAMPLE} 值为 value
${HOST} 和 ${USER} 值分别为 localhost:7272 和 robot
${ESCAPED} 值为 "quotes and spaces"
命令行-V --variablefile path * 传入文件变量
通过文件的形式传入变量,支持.py和yaml格式。
如果变量同时在命令行的变量文件中和单独指定, 则单独指定的变量有更高的优先级。
变量文件:
data1.yaml
string: Hello, world!
yamlList:
- one
- two
yamlDict:
one: yksi
two: kaksi
data2.py
city = "chengdu"
Dict = {"company": "pingan", "owner": "tangke024"}
name = "miker"
age = 23
List = [1,2,3]
testcase:
fileVariablesTest
log ${abc}
log ${name}
log ${city}
log ${age}
Log Many @{List}
Log Many &{Dict}
log ${string}
log '${yamlList}'
log ${yamlDict}
robot -d kk --variable abc:Aquotes_and_spacesA -V popTest\data1.yaml -V popTest\data2.py -v name:Tom -V popTest\data3.py:string -t test007 popTest
注意:通过-v或-V传入的参数优先级分先后,其中-v传入的单个scalar参数以最后一个为准,以-V传入的文件以最先传入的为准。
-v参数的优先级高于-V的优先级。
另外解析yaml格式需要安装PyYAML库,且yaml格式的文件不支持-V path\filename.yaml:key方式传入文件中的单个参数。
补充几点:
- 变量文件中创建的所有以下划线开头的变量不会被RF导入,如 ''_pykey'' ;除此之外,也可以使用''__all__'' (双下滑线)将真正要被RF导入的Variables的加为一个list;比如下面的例子中,就只有car、login、apple被认为是variable,而string将会被忽略;
- 为了更明确的定义list变量或者dict变量,可以在变量名称中加上前缀"LIST__" (两个下划线)或者 "DICT__"。RF中引用该变量时,不会把前缀当成变量名的一部分。前缀的作用是告诉RF该变量将会是"list-like"或者"dict-like"类型,框架会执行响应的检查验证。
- 通常来说,全局变量名称应该大写,非全局变量小写。
data.py
string="sssss"
apple = "yad"
LIST__car = ['bus', 'jep']
DICT__login = {"username": "miker", "pwd": "dlg"}
__all__ = ["LIST__car", "apple", "DICT__login"]
动态创建变量
既然-V --variablefile path * 支持.py格式文件,那么py文件中的方法和特定函数均可用来作为变量传递。
如时间戳
import os
import random
import time
import datetime
PATH = os.getcwd() #获得当前路径
RANDOM_INT = random.randint(0,9999)
CURRENT_TIME = time.time()
NOW = datetime.datetime.now()
YEAR = NOW.year
MONTH = NOW.month
HOUR = NOW.hour
使用特殊函数
特别的,RF支持.py使用特殊函数,即get_variables()和getVariables(),该函数将变量按字典的形式返回,该函数还可以接受参数,。如果这个函数存在,Robot Framework将调用该函数,并且预期返回的结果是Python的字典类型或者Java中的 Map 类型, 其中变量的名称是键,而值就是变量的值。
使用方法:
data.py
def getVariables(env = 'stg'):
if env == 'prd':
DICT__variables = {"host": "localhost", "port": "8080"}
else:
DICT__variables = {"host": "service.domain.com", "port": "80"}
globalVariable = {"UUID": "Tentant_ks8283", "resouceID": "9928s9f9rkw22"}
DICT__variables["globalVariable"] = globalVariable
return DICT__variables
上述代码中,getVariables方法有参数env,可以通过该方式传入不同的环境code,达到引用不同的变量。
在RF对应的suite上导入该data.py文件变量,并设置变量env,如下:
在进行命令行调用时,可以传入对应的env,达到返回对应的参数的目的。
通过get_variables()和getVariables()方式返回的变量,引用时直接写入变量的key,返回即为变量的value。如果变量中含有全局变量或者list变量,需要针对不同的方式进行获取。
RF测试用例如下:
log &{globalVariable}[UUID]
log ${globalList[1]}
log ${host}
命令行如下:
robot -v env:prd -t testcase testDir
or
robot -t testcase testDir # env取默认值
通过该方式不用传入-V文件。
特别注意:
- 通过特定函数的方式传入文件参数时,非特定函数变量不能与特定函数变量放于同一文件中,必须分开放,否则获取不到非特定函数变量。
更新内存中变量值
在某些特定场景中,想要在用例里改变变量文件中某变量的值,并且后续用例里用改变后的值,可以通过Evaluate关键字,使用python代码直接进行list、dict或者操作代码进行修改变量值,如:利用字典update方法将改变内存里的值的特性。
log ${car}
${new} Set Variable bike
Evaluate $car.append('${new}')
Evaluate $car.remove('${car}[0]')
Evaluate $car.insert(${0}, 'aircraft')
log ${car}
内置变量
Robot Framework提供了一些可自动使用的内置变量。
操作系统变量
与操作系统相关的内置变量使测试数据与操作系统无关。
变量 | 说明 |
---|---|
$ {CURDIR} | 测试数据文件所在目录的绝对路径。此变量区分大小写。 |
$ {TEMPDIR} | 系统临时目录的绝对路径。在类UNIX系统中,这通常是/ tmp,在Windows c:\Documents and Settings<user>\Local Settings\Temp中。 |
$ {EXECDIR} | 从中开始测试执行的目录的绝对路径。Robot Framework 2.1中的新功能。 |
$ {/} | 系统目录路径分隔符。/在类UNIX系统中,\在Windows中。 |
$ {:} | 系统路径元素分隔符。:在类UNIX系统中; 在Windows中。 |
Test Case | Action | Argument | Argument |
---|---|---|---|
Example | Create File | ${CURDIR}${/}input.data | Some text here |
Set Environment Variable | CLASSPATH | ${TEMPDIR}${:}${TEMPDIR}${/}foo.jar |
数字变量
变量语法可用于创建整数和浮点数,如下例所示。当关键字期望获得实际数字而不是看起来像数字的字符串作为参数时,这非常有用。
从Robot Framework 2.6开始,也可以分别使用0b,0o 和0x前缀从二进制,八进制和十六进制值创建整数。语法是区分大小写的。
Test Case | Action | Argument | Argument |
---|---|---|---|
Example | Should Be Equal | ${0b1011} | ${11} |
Should Be Equal | ${0o10} | ${8} | |
Should Be Equal | ${0xff} | ${255} | |
Should Be Equal | ${0B1010} | ${0XA} |
另外,在RF中进行数值变量运算时,必须使用Evaluate关键字,意在在python环境中运行python代码。否则会当成string进行运算。
test
${string} Set Variable 2019
${stringAdd} Set Variable ${string}+1
${numAdd} Evaluate ${string}+1
* INFO : ${string} = 2019
* INFO : ${stringAdd} = 2019+1
* INFO : ${numAdd} = 2020
布尔值和None/null变量
此外,布尔值和Python None和Java null可以使用与数字类似的变量语法创建。
test
${testTrue} Set Variable ${true}
${trueType}= Evaluate type($testTrue)
${testNone} Set Variable ${none}
${testNull} Set Variable ${null}
* INFO : ${testTrue} = True
* INFO : ${trueType} = <type 'bool'>
* INFO : ${testNone} = None
* INFO : ${testNull} = None
这些变量不区分大小写,例如$ {True}和$ {true}是等效的。此外,$ {None}和$ {null}是同义词,因为在Jython解释器上运行测试时,Jython会在必要时自动将None和 null转换为正确的格式。
空格和Empty变量
可以分别使用变量${SPACE}和 ${EMPTY}创建空格和空字符串 。例如,当需要时,这些变量是有用的使用反斜杠转义空格或空单元格时。如果需要多个空格,则可以使用扩展变量语法,如 $ {SPACE * 5}。在下面的示例中,Should Be Equal关键字获取相同的参数,但使用变量的参数比使用反斜杠的参数更容易理解。
Test Case | Action | Argument | Argument |
---|---|---|---|
One Space | Should Be Equal | ${SPACE} | \ |
Four Spaces | Should Be Equal | ${SPACE * 4} | \ |
Quoted Space | Should Be Equal | "${SPACE}" | " " |
Quoted Spaces | Should Be Equal | "${SPACE * 2}" | " " |
Empty | Should Be Equal | ${EMPTY} | \ |
自动变量
自动变量被RF框架创建和修改,在测试执行过程中值可能会变化;另外,某些自动变量在执行过程中并非总是可用。
修改自动变量,并不能对变量的初始值产生影响。但可以用某些内建关键字来修改某些自动变量的值。
变量 | 描述 | 使用范围 |
---|---|---|
${TEST NAME} | 当前测试用例的名称 | 测试用例内 |
@{TEST TAGS} | 当前测试用的Tags | 测试用例内 |
${TEST DOCUMENTATION} | 当前测试用例的文档 | 测试用例内 |
${TEST STATUS} | 当前测试用例的测试结果,PASS或FAIL | Test teardown |
${TEST MESSAGE} | 当前测试用的的测试结果信息 | Test teatdown |
${PREV TEST NAME} | 上一条测试用例的名称,如果没有则值为空 | 任意 |
${PREV TEST STATUS} | 上一条测试用例的结果,如果没有则值为空 | 任意 |
${PREV TEST MESSAGE} | 上一条测试用例的结果信息,如果没有则值为空 | 任意 |
${SUITE NAME} | 当前测试集的全称 | 任意 |
${SUITE SOURCE} | 当前测试集的绝对路径 | 任意 |
${SUITE DOCUMENTATION} | 当前测试集的描述,可以通过Set Suite Documentation修改 | 任意 |
&{SUITE METADATA} | 当前测试集的METADATA,可以通过Set Suite Metadata修改 | 任意 |
${SUITE STATUS} | 当前测试集的测试状态 | Suite teardown |
${SUITE MESSAGE} | 当前测试集的测试状态信息 | Suite teardown |
${KEYWORD STATUS} | 当前关键字的状态 | Keyword teardown |
${KEYWORD MESSAGE} | 当前关键字的状态信息 | Keyword teardown |
${LOG LEVEL} | 当前的日志级别 | 任意 |
${OUTPUT FILE} | output文件的绝对路径 | 任意 |
${LOG FILE} | log文件的绝对路径,如果没有则为None | 任意 |
${REPORT FILE} | report文件的绝对路径,如果没有则为None | 任意 |
${DEBUG FILE} | debug文件的绝对路径,如果没有则为None | 任意 |
${OUTPUT DIR} | output文件夹的绝对路径 | 任意 |
举个例子:
新建用户关键字,如下:
输出测试用例名和测试结果。
将其设置为suite 的Test Teardown,使每一个测试用例执行完毕后调用该关键字。
测试用例如下:
*** Test Cases ***
test001
Should Be Equal 1 2
test002
Should Be Equal 1 1
执行结果:
Starting test: *.test001
* FAIL : 1 != 2
* INFO : test001 test result is : FAIL !
Ending test: *.test001
Starting test: *.test002
* INFO : test002 test result is : PASS !
Ending test: *.test002
变量的作用域
在通常情况下,每个变量默认都是局部变量,在默认情况下,变量的作用域为:
- 一个case里的变量,作用域在这个case内部;
- 一个userkeyword里的变量,作用域在这个userkeyword内部;
- 一个文件型suite里的变量,作用域在这个suite内部,所有下级case都可以使用;
- 一个目录型suite里的变量,作用域在这个目录内,但是它下级文件型suite是无法使用的,所以一般在目录下新增变量没有太大意义;
- 全局变量:命令行中或使用Set Global Variable定义的变量为全局变量,在任意地方都可以使用,另外内置变量也是一种全局变量;
- 测试集变量:在变量表格,引入的资源或变量文件以及使用Set suite Variable定义的变量为测试集变量,在测试集内可用;
- 测试用例变量:由Set Test Variable定义的变量为测试用例变量,测试用例范围内,包括关键字都可以使用,初始状态下没有变量为此类变量;
- 本地变量:由Set Variable定义的变量或者测试用例或关键字中由关键字返回或关键字参数的变量,该变量只能在测试用例或关键字范围内可用。
变量的作用域是可以改变的,通过一些关键字的处理,对变量进行作用域的改变,常用的关键字有:
Set Global Variable为设定全局变量。当执行过这个设置后,这个变量在所有的测试案例和测试套件中都有效;
Set Suite Variable为设定File Suite级变量。当执行过这个设置后,这个变量在当前的File Suite内都有效;
Set Test Variable为设定Case级变量。当执行过这个设置后,这个变量在当前的Test Case内有效;
*** Test Cases ***
test
${v1} Set Variable value1
${v2} Set Variable value2
${v3} Set Variable value3
${v4} Set Variable value4
Set Test Variable ${v2}
Set Suite Variable ${v3}
Set Global Variable ${v4}
变量的优先级
内置变量-->>测试中定义-->>命令行中定义-->>变量表格-->>资源文件
- 命令行中定义的变量在测试开始执行前被定义,定义的变量会覆盖测试文件变量表格和资源文件中定义的变量。
- 测试文件变量表格中定义的变量,在当前测试文件中全局可用,可能会覆盖资源文件和变量文件中的变量。
- 资源文件和变量文件中定义的变量在测试文件中优先级最低,如果他们之间存在重复,则最先引入的文件的变量优先级最高。
- 测试执行中定义的变量拥有最高优先级,但它的作用域仅限于当前测试。
- 内置变量不可被覆盖。
扩展说明
变量优先级
命令行中的变量
在命令行中设置的变量具有在实际测试执行开始之前可以设置的所有变量的最高优先级。它们覆盖在测试用例文件中的变量表中以及在测试数据中导入的资源和变量文件中创建的可能变量。
单独设置变量(--variable option)会覆盖使用变量文件变量设置的启动脚本中(--variablefile选项)。如果多次指定相同的单个变量,则最后指定的变量将覆盖之前的变量。这允许在设置变量的默认值,并从命令行覆盖它们。但请注意,如果多个变量文件具有相同的变量,则首先指定的文件中的变量具有最高优先级。
测试用例文件中的变量表
使用测试用例文件中的Variable表变量创建的可用于该文件中的所有测试用例。这些变量会覆盖导入的资源和变量文件中具有相同名称的可能变量。
在变量表中创建的变量在创建它们的文件中的所有其他表中都可用。这意味着它们也可以在Setting表中使用,例如,用于从资源和变量文件导入更多变量。
导入的资源和变量文件
从资源和变量文件变量导入的具有在测试数据中创建的所有变量的最低优先级。资源文件和变量文件中的变量具有相同的优先级。如果多个资源和/或变量文件具有相同的变量,则首先导入的文件中的变量将被使用。
如果资源文件导入资源文件或变量文件,则其自己的Variable表中的变量具有比它导入的变量更高的优先级。所有这些变量都可用于导入此资源文件的文件。
请注意,从资源和变量文件导入的变量在导入它们的文件的变量表中不可用。这是因为在导入资源文件和变量文件的设置表之前处理变量表。
在测试执行期间设置的变量
在测试执行期间使用关键字内置或关键字的返回值设置的变量Set Test / Suite / Global Variable始终覆盖设置范围内的可能现有变量。从某种意义上说,它们具有最高优先级,但另一方面它们不会影响它们所定义范围之外的变量。
内置变量
内置变量(数字变量如${TEAMDIR}或${TEST_NAME}) 具有所有变量的最高优先级。它们不能使用Variable表或命令行覆盖,但即使它们也可以在测试执行期间重置。此规则的一个例外是变量,如果没有找到,则动态解析。因此可以覆盖它们,但这通常是一个坏主意。另外$ {CURDIR} 是特殊的,因为它在测试数据处理期间已被替换。
变量作用范围
根据创建的位置和方式,变量可以具有全局,测试套件,测试用例或用户关键字范围。
全局变量
全局变量在测试数据中随处可用。这些变量通常使用 --variable和--variablefile选项从命令行设置BuiltIn关键字,但也可以使用内置变量变量Set Global Variable在测试数据中的任何位置创建新的全局变量或更改现有变量。此外,也是全局。
建议对所有全局变量使用大写字母。
测试套件范围
具有测试套件范围的变量可在测试套件中的任何位置使用,可在其中定义或导入。它们可以在变量表中创建,从资源和变量文件BuiltIn关键字导入,或者在测试执行期间使用Set Suite Variable进行设置。
测试套件范围不是递归的,这意味着更高级别测试套件中的可用变量在低级套件中不可用。如有必要,可以使用资源和变量文件来共享变量。
由于这些变量可以在使用它们的测试套件中被视为全局变量,因此建议使用大写字母。
测试用例范围
在测试用例中根据关键字的返回值创建的变量具有测试用例范围,并且仅在该测试用例中可用。创建它们的另一种可能性是在该特定测试用例中的任何位置使用BuiltIn关键字Set Test Variable。测试用例变量是本地的,应该使用小写字母。
用户关键字范围
用户关键字从传递给它们的参数中获取自己的变量, 并从它们使用的关键字返回值。这些变量也是本地的,应该使用小写字母。