声明:本文搬运自官方操作文档,仅用作学习,有错误的地方欢迎指正。
官方文档链接:RobotFramework--资源和变量文件
2.7 资源和变量文件
测试用例文件和测试套件初始化文件中的用户关键字和变量只能用于创建它们的文件,但资源文件提供了共享它们的机制。由于资源文件结构非常接近测试用例文件,因此很容易创建。
变量文件为创建和共享变量提供了强大的机制。例如,它们允许字符串以外的值,并允许动态创建变量。这种灵活性来自于使用 Python 代码创建的实例,这也表明它们比变量表复杂一些。
2.7.1 资源文件
使用资源文件
资源文件使用Setting表中的Resource设置导入。资源文件路径在setting name后的单元格。
如果填绝对路径可以直接使用。在其他情况下,优先到导入文件所在的目录进行搜索。如果找不到则到 PYTHONPATH 中搜索该文件。path可包含变量,建议使用单独系统路径(例如,${RESOURCES}/login_resources.html或${RESOURCE_PATH})。此外,Windows 上路径中的斜线("/")会自动改为反斜线("\")。

资源文件中定义的用户关键字和变量可在使用该资源文件的文件中可用。同样可用的还有来自该资源文件导入的库、资源文件和变量文件的所有关键字和变量。
资源文件结构
资源文件的较高级别结构与测试用例文件相同,当然不包含测试用例表。此外,资源文件中的设置表只能包含导入设置(Library, Resource, Variables)和**Documentation。变量表和关键字表的使用方式与测试用例文件完全相同。
如果多个资源文件具有同名的用户关键字,则必须使用将资源文件名称作为关键字名称的前缀,而无需扩展(例如,myresources.Some Keyword和common.Some Keyword)。此外,如果多个资源文件包含相同的变量,则首先使用第一个导入的。
资源文件文档
使用[Documentation]设置可以记录资源文件中创建的关键字。从RobotFramework 2.1 开始,资源文件本身也可以在设置表中具有类似于测试套件的文档。
libdoc和RIDE都使用这些文档,它们自然适用于任何打开资源文件的任何人。关键字文档的第一行在运行时会被记录,但在测试执行过程中会忽略资源文件文档。
资源文件示例


2.7.2 变量文件
变量文件包含用于测试数据的变量。也可以使用变量表创建变量表或从命令行设置变量,但变量文件允许动态创建它们,变量也可以包含任何对象。
变量文件通常作为 Python 模块实现,并且有两种不同的方法创建变量:
直接创建变量
变量指定为模块属性。在简单的情况下,语法是如此简单,不需要真正的编程。例如,MY_VAR = 'my value'就是创建了一个指定字符串的变量${MY_VAR}。
从特殊函数获取变量
变量文件有一个特殊的方法get_variables(或getVariables)将变量作为map返回。因为这种方法可以携带参数,也非常灵活。
变量文件也可以选择使用作为Python 或 Java 类实现。此外,也可以将变量创建为属性或从特殊方法获取变量。
使用变量文件
Setting表
所有测试数据文件都可以使用Setting表中的Variables设置导入变量,就像使用Resource**设置导入资源文件一样。与资源文件类似,导入变量文件的路径与导入文件所在的目录相对应,如果找不到,则从 PYTHONPATH 搜索。路径可以包含变量, Windows 上的斜线转换为反斜线。如果参数文件携带参数,则它们在path后的单元格中指定,并且它们也可以包含变量。

变量文件的所有变量都可以在导入该文件的测试数据文件中找到。如果导入多个变量文件并包含同名变量,则使用最早导入的文件中的变量。此外,在变量表中创建的变量和命令行设置的变量会覆盖变量文件中的变量。
命令行
使用变量文件的另一种方法是使用命令行选项--variablefile。变量文件使用路径引用,并且可以携带参数,使用冒号 (:)连接
--variablefile myvariables.py
--variablefile path/variables.py
--variablefile /absolute/path/common.py
--variablefile taking_arguments.py:arg1:arg2
测试数据文件中,这些文件中的变量都是全局变量,类似于使用--variable设置的单个变量。 如果同时使用--variablefile和--variable选项,并且存在具有相同名称的变量,则优先设置--variable选项。
直接创建变量
基本语法
当使用变量文件时会被作为 Python 模块导入,并且所有不以下划线(_)开头的变量都拥有全局属性。由于变量名称不区分大小写,座椅上下级名称可能相同。全局变量和属性建议使用大写字母。
VARIABLE = "An example string"
ANOTHER_VARIABLE = "This is pretty easy!"
INTEGER = 42
STRINGS = ["one", "two", "kolme", "four"]
NUMBERS = [1, INTEGER, 3.14]
在上示例中,创建了${VARIABLE},${ANOTHER VARIABLE}等变量。前两个变量是字符串,第三个是整数,后两个是列表。这些甚至包括以列表为值的变量都是标量。要创建列表变量,变量名称必须使用前缀LIST__(注意是两个下划线)。
LIST__STRINGS = ["list", "of", "strings"]
LIST__MIXED = ["first value", -1.1, None, True]
上述两个示例中的变量也可以使用变量表创建。

将对象作为值
变量文件中的变量不限于字符串这种基本类型作为变量表的值。相反,变量可以包含任何对象。在下面的示例中,变量${MAPPING}有两个Java 哈希表(此示例仅适合运行在 Jython)。
from java.util import Hashtable
MAPPING = Hashtable()
MAPPING.put("one", 1)
MAPPING.put("two", 2)
第二个示例中${MAPPING}为 Python 字典,并且还具有从同一文件中实现的自定义对象创建的两个变量。
MAPPING = {'one': 1, 'two': 2}
class MyObject:
def __init__(self, name):
self.name = name
OBJ1 = MyObject('John')
OBJ2 = MyObject('Jane')
创建动态变量
由于变量文件是使用真正的编程语言创建的,因此具有设置变量的动态逻辑。
import os
import random
import time
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
上面使用标准 Python 库设置不同的变量,也可以使用自己的代码构建值。以下示例说明了该概念,但同样可以从数据库、外部文件中读取数据,甚至可以向用户询问数据。
import math
def get_area(diameter):
radius = diameter / 2
area = math.pi * radius * radius
return area
AREA1 = get_area(1)
AREA2 = get_area(2)
引用变量值
当RobotFramework处理变量文件时,所有不以下划线开头的属性都会识别为变量。这意味着,即使在变量文件中创建的函数或类或从其他地方导入的函数或类也被视为变量。最后一个例子包含变量${math}和${get_area}除了${AREA1}和${AREA2}。
通常额外的变量不会导致问题,但它们可能会覆盖其他变量导致难以定位的错误。忽略其他属性的一种可能性是用下划线来作为前缀:
import math as _math
def _get_area(diameter):
radius = diameter / 2.0
area = _math.pi * radius * radius
return area
AREA1 = _get_area(1)
AREA2 = _get_area(2)
如果有很多属性,不需要所有都加下划线前缀,通常使用特殊属性all并给它一个属性列表将其作为变量处理。
import math
__all__ = ['AREA1', 'AREA2']
def get_area(diameter):
radius = diameter / 2.0
area = math.pi * radius * radius
return area
AREA1 = get_area(1)
AREA2 = get_area(2)
注意
__all__属性也是,最初,使用Python决定了属性导入使用语法from modulename import *.
从特殊方法获取变量
获取变量的另一种方法是使用变量文件中的特殊方法get_variables(也可以使用驼峰命名getVariables)。如果RobotFramework检测到这样的函数会自动调用,并以键值对的形式将变量转化为 Python 字典或 JavaMap。除非前缀有LIST__,否则变量都被识别为标量,且可以包含任何值。下面示例效果与直接在上面创建变量的第一个示例相同。
def get_variables():
variables = {"VARIABLE ": "An example string",
"ANOTHER_VARIABLE": "This is pretty easy!",
"INTEGER": 42,
"STRINGS": ["one", "two", "kolme", "four"],
"NUMBERS": [1, 42, 3.14],
"LIST__STRINGS": ["list", "of", "strings"],
"LIST__MIXED": ["first value", -1.1, None, True]}
return variables
get_variables也可以携带参数,这有助于改变实际创建的变量。函数的参数设置与 Python 函数一样。在测试数据中使用变量文件时,参数在path之后的单元中指定,在命令行中,它们与路径以冒号隔开。
下面模拟了如何使用变量文件的参数。在现实使用中,该参数可能会从外部文本文件或数据库中读取变量。
variables1 = {'scalar': 'Scalar variable',
'LIST__list': ['List','variable']}
variables2 = {'scalar' : 'Some other value',
'LIST__list': ['Some','other','value'],
'extra': 'variables1 does not have this at all'}
def get_variables(arg):
if arg == 'one':
return variables1
else:
return variables2
用Python或Java类实现变量文件
从RobotFramework 2.7 开始,可以实现变量文件作为 Python 或 Java 类。
实现
由于变量文件始终使用文件系统路径导入,因此创建它们作为类有一些限制:
- Python 类必须与它们所在的模块具有相同的名称。
- Java 类必须位于默认包中。
- Java类的路径必须以.java或.class结束。这两种情况都必须存在类文件。
无论使用哪种语言,该框架将创建一个不使用参数的类实例,并且将从实例中获得变量。与模块类似,变量可以直接定义为实例中的属性,也可以使用get_variables(或getVariables)方法获取。
当变量在实例中直接定义时,将忽略包含可调用值的所有属性,以避免从实例方法创建变量。如果您实际上需要可调用变量,则需要使用其他方法创建变量文件。
示例
第一个示例使用 Python 和 Java 从属性中创建变量。两者都从类属性中创建变量${VARIABLE}和@{LIST},从实例属性创建 ${ANOTHER VARIABLE} 。
class StaticPythonExample(object):
variable = 'value'
LIST__list = [1, 2, 3]
_not_variable = 'starts with an underscore'
def __init__(self):
self.another_variable = 'another value'
public class StaticJavaExample {
public static String variable = "value";
public static String[] LIST__list = {1, 2, 3};
private String notVariable = "is private";
public String anotherVariable;
public StaticJavaExample(String arg1, String arg2) {
anotherVariable = "another value";
}
}
第二个例子利用动态方法获取变量。两者都只创建一个变量${DYNAMIC VARIABLE}。
class DynamicPythonExample(object):
def get_variables(self, *args):
return {'dynamic variable': ' '.join(args)}
import java.util.Map;
import java.util.HashMap;
public class DynamicJavaExample {
public Map<String, String> getVariables(String arg1, String arg2) {
HashMap<String, String> variables = new HashMap<String, String>();
variables.put("dynamic variable", arg1 + " " + arg2);
return variables;
}
}