Robot Framework 新版教程 - 创建用户关键字
(Robot Framework 7.x 教程, Part 6)
Keywords section 用于将已有关键字组合在一起,创建新的更高层级的关键字。这类关键字称为用户关键字(user keywords),以区别于在测试库中实现的最底层库关键字(library keywords)。创建用户关键字的语法与创建测试用例的语法非常接近,因此很容易上手。
用户关键字语法
基本语法
在许多方面,用户关键字的整体语法与测试用例的语法是一致的。用户关键字在 Keywords section 中创建,与 Test Cases section 的区别仅在于标识名称不同。用户关键字的名称位于第一列,与测试用例名称类似。用户关键字同样由关键字构成,这些关键字可以来自测试库,也可以是其他用户关键字。关键字名称通常位于第二列,但在通过关键字返回值设置变量时,变量名位于前面的列,关键字名称则在其后。
*** Keywords ***
Open Login Page
Open Browser http://host/login.html
Title Should Be Login Page
Title Should Start With
[Arguments] ${expected}
${title} = Get Title
Should Start With ${title} ${expected}
大多数用户关键字需要接收参数。上面的第二个示例已经用到了这一重要功能,本节后续将详细说明,用户关键字的返回值也将一并介绍。
用户关键字可以在套件文件、资源文件和套件初始化文件中创建。在资源文件中创建的关键字可供引用该资源文件的文件使用,而其他关键字仅在其所在文件中可用。
Keywords section 中的设置项
用户关键字可以拥有与测试用例类似的设置项,并且使用相同的方括号语法来区分设置名与关键字名。所有可用的设置项如下,本节后续将逐一说明:
[Documentation],用于设置用户关键字的文档。[Tags],为关键字设置标签。[Arguments],指定用户关键字的参数。[Setup]、[Teardown],指定用户关键字的 setup 和 teardown。[Setup]是 Robot Framework 7.0 的新功能。[Timeout],设置用户关键字的超时时间。超时设置将在专门章节详细讨论。[Return],指定用户关键字的返回值。该设置在 Robot Framework 7.0 中已弃用,应改用 RETURN 语句。
上述格式是推荐写法,但设置名称不区分大小写,方括号与名称之间允许有空格。例如
[ TAGS ]也是有效的。
用户关键字名称和文档
用户关键字的名称定义在 Keywords section 的第一列。名称应具有描述性,使用较长的关键字名称也完全可以。实际上,在创建用例式的测试用例时,最高层级的关键字往往被写成句子甚至段落的形式。
用户关键字可以通过 [Documentation] 设置项添加文档。它支持与测试用例文档相同的格式化、多行拆分等功能。该设置用于在测试数据中记录用户关键字的文档,也会显示在 Libdoc 工具从资源文件生成的正式关键字文档中。文档的第一个逻辑行(直到第一个空行)会作为关键字文档显示在测试日志中。
*** Keywords ***
One line documentation
[Documentation] One line documentation.
No Operation
Multiline documentation
[Documentation] The first line creates the short doc.
...
... This is the body of the documentation.
... It is not shown in Libdoc outputs but only
... the short doc is shown in logs.
No Operation
Short documentation in multiple lines
[Documentation] If the short doc gets longer, it can span
... multiple physical lines.
...
... The body is separated from the short doc with
... an empty line.
No Operation
有时关键字需要被移除、替换或因其他原因标记为弃用。用户关键字可以通过在文档开头添加 *DEPRECATED* 来标记为弃用,使用该关键字时会触发警告。更多信息请参阅"弃用关键字"章节。
在 Robot Framework 3.1 之前,简短文档仅包含关键字文档的第一个物理行。
用户关键字标签
用户关键字和库关键字都可以拥有标签。与为测试用例打标签类似,有两种设置会影响用户关键字的标签:
Settings section 中的 Keyword Tags 设置:拥有此设置的文件中的所有关键字都会获得指定的标签。
每个关键字的 [Tags] 设置:关键字除了通过 Keyword Tags 指定的标签外,还会获得这些标签。[Tags] 设置还允许通过 -tag 语法移除 Keyword Tags 设置的标签。
*** Settings ***
Keyword Tags gui html
*** Keywords ***
No own tags
[Documentation] Keyword has tags 'gui' and 'html'.
No Operation
Own tags
[Documentation] Keyword has tags 'gui', 'html', 'own' and 'tags'.
[Tags] own tags
No Operation
Remove common tag
[Documentation] Test has tags 'gui' and 'own'.
[Tags] own -html
No Operation
关键字标签支持使用变量,-tag 语法支持模式匹配等,与测试用例标签完全一致。
除了使用专门的设置项外,还可以在文档的最后一行通过 Tags: 前缀指定关键字标签,标签之间用逗号分隔。例如,以下两个关键字获得相同的三个标签:
*** Keywords ***
Settings tags using separate setting
[Tags] my fine tags
No Operation
Settings tags using documentation
[Documentation] I have documentation. And my documentation has tags.
... Tags: my, fine, tags
No Operation
关键字标签会显示在日志和 Libdoc 生成的文档中,在文档中还可以根据标签搜索关键字。--removekeywords 和 --flattenkeywords 命令行选项也支持按标签选择关键字,后续版本可能会为关键字标签添加更多用途。
与测试用例标签类似,带有 robot: 前缀的用户关键字标签是 Robot Framework 本身为特殊功能保留的。因此,用户不应使用带有此前缀的标签,除非确实需要激活特定功能。从 Robot Framework 6.1 开始,可以使用保留标签 robot:flatten 在执行时启用关键字扁平化功能。
Keyword Tags是 Robot Framework 6.0 的新功能。在更早版本中,所有关键字标签都需要通过[Tags]设置指定。
用于移除公共标签的
-tag语法是 Robot Framework 7.0 的新功能。
用户关键字参数
大多数用户关键字需要接收参数。指定参数的语法可能是 Robot Framework 中最复杂的常用功能,但即便如此也相对简单,特别是在最常见的场景中。参数通常通过 [Arguments] 设置项指定,参数名使用与变量相同的语法,例如 ${arg}。
位置参数
指定参数最简单的方式(除了完全不使用参数外)是只使用位置参数。在大多数情况下,这就够用了。
语法是先给出 [Arguments] 设置,然后在后续单元格中定义参数名。每个参数占一个独立的单元格,使用与变量相同的语法。调用关键字时必须提供与签名中参数名数量一致的参数。参数的实际名称对框架本身没有影响,但从用户角度来看,名称应尽可能具有描述性。推荐使用小写字母命名变量,格式如 ${my_arg}、${my arg} 或 ${myArg}。
*** Keywords ***
One Argument
[Arguments] ${arg_name}
Log Got argument ${arg_name}
Three Arguments
[Arguments] ${arg1} ${arg2} ${arg3}
Log 1st argument: ${arg1}
Log 2nd argument: ${arg2}
Log 3rd argument: ${arg3}
带默认值的参数
创建用户关键字时,位置参数在大多数场景下已经足够。但有时为部分或全部参数提供默认值会更方便。用户关键字同样支持默认值,所需的新语法在前面讨论的基本语法基础上增加不多。
简单来说,默认值通过等号(=)附加在参数后面,例如 ${arg}=default。可以有多个带默认值的参数,但它们都必须位于普通位置参数之后。默认值可以包含在测试、套件或全局作用域中创建的变量,但不能使用关键字执行器的局部变量。默认值也可以基于关键字接受的前面的参数来定义。
默认值的语法对空格敏感。
=号前不允许有空格,=号后的空格将被视为默认值的一部分。
*** Keywords ***
One Argument With Default Value
[Arguments] ${arg}=default value
[Documentation] This keyword takes 0-1 arguments
Log Got argument ${arg}
Two Arguments With Defaults
[Arguments] ${arg1}=default 1 ${arg2}=${VARIABLE}
[Documentation] This keyword takes 0-2 arguments
Log 1st argument ${arg1}
Log 2nd argument ${arg2}
One Required And One With Default
[Arguments] ${required} ${optional}=default
[Documentation] This keyword takes 1-2 arguments
Log Required: ${required}
Log Optional: ${optional}
Default Based On Earlier Argument
[Arguments] ${a} ${b}=${a} ${c}=${a} and ${b}
Should Be Equal ${a} ${b}
Should Be Equal ${c} ${a} and ${b}
当关键字接受多个带默认值的参数且只需覆盖其中部分参数时,使用命名参数语法通常很方便。对用户关键字使用此语法时,参数名不带 ${} 修饰。例如,上面的第二个关键字可以如下使用,${arg1} 仍然保持默认值:
*** Test Cases ***
Example
Two Arguments With Defaults arg2=new value
所有 Python 使用者一定注意到了,指定默认参数的语法深受 Python 函数默认值语法的启发。
可变数量的参数
有时即使默认值也不够用,需要关键字能接受可变数量的参数。用户关键字同样支持此功能。只需在可能的位置参数之后,在关键字签名中使用列表变量(如 @{varargs})。此语法可以与前面描述的默认值组合使用,最终列表变量会接收所有不匹配其他参数的剩余参数。因此列表变量可以包含任意数量的元素,包括零个。
*** Keywords ***
Any Number Of Arguments
[Arguments] @{varargs}
Log Many @{varargs}
One Or More Arguments
[Arguments] ${required} @{rest}
Log Many ${required} @{rest}
Required, Default, Varargs
[Arguments] ${req} ${opt}=42 @{others}
Log Required: ${req}
Log Optional: ${opt}
Log Others:
FOR ${item} IN @{others}
Log ${item}
END
注意,如果上面最后一个关键字使用了超过一个参数,第二个参数 ${opt} 总是获得给定的值而非默认值,即使给定的值为空也是如此。最后一个示例还展示了用户关键字接受的可变数量参数如何在 FOR 循环中使用。这两个较为高级的功能的组合有时非常有用。
上述示例中的关键字可以如下使用:
*** Test Cases ***
Varargs with user keywords
Any Number Of Arguments
Any Number Of Arguments arg
Any Number Of Arguments arg1 arg2 arg3 arg4
One Or More Arguments required
One Or More Arguments arg1 arg2 arg3 arg4
Required, Default, Varargs required
Required, Default, Varargs required optional
Required, Default, Varargs arg1 arg2 arg3 arg4 arg5
同样,Python 使用者会注意到可变数量参数的语法与 Python 非常接近。
自由命名参数
用户关键字还可以通过在最后一个参数位置使用字典变量(如 &{named})来接受自由命名参数。调用关键字时,该变量将接收所有不匹配任何位置参数或仅限命名参数的命名参数。
*** Keywords ***
Free Named Only
[Arguments] &{named}
Log Many &{named}
Positional And Free Named
[Arguments] ${required} &{extra}
Log Many ${required} &{extra}
Run Program
[Arguments] @{args} &{config}
Run Process program.py @{args} &{config}
上面最后一个示例展示了如何创建一个接受任意位置参数和命名参数并将其转发的封装关键字。完整示例请参考自由命名参数的示例。
用户关键字中的自由命名参数支持与 Python 中的 kwargs 工作方式类似。在签名中以及转发参数时,&{kwargs} 与 Python 的 **kwargs 基本等价。
仅限命名参数
用户关键字支持仅限命名参数,其灵感来自 Python 的仅限关键字参数。此语法通常将普通参数放在可变数量参数(@{varargs})之后。如果关键字不使用可变参数,可以使用 @{} 表示后续参数为仅限命名参数:
*** Keywords ***
With Varargs
[Arguments] @{varargs} ${named}
Log Many @{varargs} ${named}
Without Varargs
[Arguments] @{} ${first} ${second}
Log Many ${first} ${second}
仅限命名参数可以与位置参数和自由命名参数一起使用。使用自由命名参数时,它们必须位于最后:
*** Keywords ***
With Positional
[Arguments] ${positional} @{} ${named}
Log Many ${positional} ${named}
With Free Named
[Arguments] @{varargs} ${named only} &{free named}
Log Many @{varargs} ${named only} &{free named}
传递仅限命名参数给关键字时,它们的顺序不重要,但必须跟在可能的位置参数之后。上述关键字可以如下使用:
*** Test Cases ***
Example
With Varargs named=value
With Varargs positional second positional named=foobar
Without Varargs first=1 second=2
Without Varargs second=toka first=eka
With Positional foo named=bar
With Positional named=2 positional=1
With Free Named positional named only=value x=1 y=2
With Free Named foo=a bar=b named only=c quux=d
仅限命名参数可以像普通用户关键字参数一样拥有默认值。一个小区别是带默认值和不带默认值的参数的顺序不重要。
*** Keywords ***
With Default
[Arguments] @{} ${named}=default
Log Many ${named}
With And Without Defaults
[Arguments] @{} ${optional}=default ${mandatory} ${mandatory 2} ${optional 2}=default 2 ${mandatory 3}
Log Many ${optional} ${mandatory} ${mandatory 2} ${optional 2} ${mandatory 3}
参数类型转换
用户关键字支持基于显式指定类型的自动参数转换。类型语法 ${name: type} 与创建变量时的用法相同,支持的转换也相同。
普通参数的基本用法非常简单。只需像 ${count: int} 这样指定类型,传入的值就会自动转换。如果参数有默认值(如 ${count: int}=1),默认值也会被转换。如果转换失败,调用关键字时会报出有意义的错误信息。
*** Test Cases ***
Move around
Move 3
Turn LEFT
Move 2.3 log=True
Turn right
Failing move
Move bad
Failing turn
Turn oops
*** Keywords ***
Move
[Arguments] ${distance: float} ${log: bool}=False
IF ${log}
Log Moving ${distance} meters.
END
Turn
[Arguments] ${direction: Literal["LEFT", "RIGHT"]}
Log Turning ${direction}.
如上例所示,使用
Literal是限制可接受值的便捷方式。
对于可变数量参数,类型指定如 @{numbers: int},应用于所有参数。如果参数可能有不同类型,可以使用联合类型如 @{numbers: float | int}。对于自由命名参数,类型指定如 &{named: int},应用于所有参数值。不支持转换参数名。
*** Test Cases ***
Varargs
Send bytes Hello! Hyvä! \x00\x00\x07
Free named
Log releases rc 1=2025-05-08 rc 2=2025-05-19 rc 3=2025-05-21 final=2025-05-30
*** Keywords ***
Send bytes
[Arguments] @{data: bytes}
FOR ${value} IN @{data}
Log ${value} formatter=repr
END
Log releases
[Arguments] &{releases: date}
FOR ${version} ${date} IN &{releases}
Log RF 7.3 ${version} was released on ${date.day}.${date.month}.${date.year}.
END
用户关键字的参数类型转换是 Robot Framework 7.3 的新功能。
将参数嵌入关键字名称
上一节说明了如何将参数单独列在关键字名称之后进行传递。Robot Framework 还有另一种传递参数的方式——将参数直接嵌入到关键字名称中,如下面的第二个测试所示:
*** Test Cases ***
Normal arguments
Select from list cat
Embedded arguments
Select cat from list
如示例所示,将参数嵌入关键字名称可以让数据更易读易懂,即使是没有 Robot Framework 经验的人也能理解。
基本语法
前面的示例展示了使用 Select cat from list 比使用 Select from list 并传递 cat 作为参数更加流畅。我们当然可以把 Select cat from list 实现为一个不接受参数的普通关键字,但那样就需要为其他动物实现各种其他关键字,如 Select dog from list。嵌入式参数简化了这一过程,我们只需实现一个名为 Select ${animal} from list 的关键字,就可以用于任何动物:
*** Test Cases ***
Embedded arguments
Select cat from list
Select dog from list
*** Keywords ***
Select ${animal} from list
Open Page Pet Selection
Select Item From List animal_list ${animal}
如上所示,嵌入式参数只需在关键字名称中使用变量即可指定。名称中使用的参数在关键字内部自然可用,且根据调用方式具有不同的值。在上面的示例中,${animal} 在关键字第一次使用时值为 cat,第二次使用时值为 dog。
从 Robot Framework 6.1 开始,可以创建同时接受嵌入式参数和"普通"参数的用户关键字:
*** Test Cases ***
Embedded and normal arguments
Number of cats should be 2
Number of dogs should be count=3
*** Keywords ***
Number of ${animals} should be
[Arguments] ${count}
Open Page Pet Selection
Select Items From List animal_list ${animals}
Number of Selected List Items Should Be ${count}
除了特殊的名称外,带嵌入式参数的关键字的创建方式与其他用户关键字完全相同。使用方式也与其他关键字相同,但在匹配关键字时,名称中的空格和下划线不会被忽略。不过,它们与其他关键字一样不区分大小写。例如,Select ${animal} from list 关键字可以写作 select cow from list,但不能写作 Select cow fromlist。
嵌入式参数不支持默认值或可变数量参数等普通参数功能。如果需要此类功能,应使用普通参数。将嵌入式参数作为变量传递是可以的,但可能会降低可读性:
*** Variables ***
${SELECT} cat
*** Test Cases ***
Embedded arguments with variable
Select ${SELECT} from list
*** Keywords ***
Select ${animal} from list
Open Page Pet Selection
Select Item From List animal_list ${animal}
嵌入式参数匹配错误值
使用嵌入式参数的一个棘手之处在于,需要确保调用关键字时使用的值能匹配到正确的参数。当存在多个参数且分隔字符可能出现在给定值中时,这个问题尤为突出。例如,下面示例中的 Select Los Angeles Lakers 匹配 Select ${city} ${team} 时,${city} 包含 Los,而 ${team} 包含 Angeles Lakers:
*** Test Cases ***
Example
Select Chicago Bulls
Select Los Angeles Lakers
*** Keywords ***
Select ${city} ${team}
Log Selected ${team} from ${city}.
一个简单的解决方案是用双引号或其他实际值中不使用的字符包围参数。修正后的示例可以正确匹配城市和球队:
*** Test Cases ***
Example
Select "Chicago" "Bulls"
Select "Los Angeles" "Lakers"
*** Keywords ***
Select "${city}" "${team}"
Log Selected ${team} from ${city}.
这种方法不能解决所有冲突,但在常见场景中很有帮助,通常也推荐使用。另一个好处是它能让参数从关键字的其余部分中凸显出来。
在 Robot Framework 7.1 之前,以关键字名称开头的嵌入式参数还会匹配行为驱动开发(BDD)中常用的 Given/When/Then/And/But 前缀。例如,${name} goes home 会匹配 Given Janne goes home,导致 ${name} 的值为 Given Janne。现在前缀会被忽略,${name} 的值将是预期的 Janne。如果需要支持较旧的 Robot Framework 版本,最简单的方法是像 "${name}" goes home 这样给参数加引号以获得一致的行为。
另一种限制参数匹配值的方案是使用自定义正则表达式。
解决冲突
使用嵌入式参数时,经常会遇到多个关键字实现都能匹配所用关键字的情况。例如,下面示例中的 Execute "ls" with "-lh" 同时匹配两个关键字。它匹配 Execute "${cmd}" with "${opts}" 是显而易见且符合预期的,但它也匹配 Execute "${cmd}",此时 ${cmd} 匹配 ls" with "-lh。
*** Settings ***
Library Process
*** Test Cases ***
Automatic conflict resolution
Execute "ls"
Execute "ls" with "-lh"
*** Keywords ***
Execute "${cmd}"
Run Process ${cmd} shell=True
Execute "${cmd}" with "${opts}"
Run Process ${cmd} ${opts} shell=True
当此类冲突发生时,Robot Framework 会尝试自动选择最佳匹配。在上面的示例中,Execute "${cmd}" with "${opts}" 被认为比更通用的 Execute "${cmd}" 匹配更好,因此示例可以成功运行。
并非总能找到一个明显优于其他的匹配。例如,下面的第二个测试会失败,因为 Robot Framework 同等程度地匹配了两个关键字。这类冲突需要通过重命名关键字或使用自定义正则表达式来手动解决。
*** Test Cases ***
No conflict
Automation framework
Robot uprising
Unresolvable conflict
Robot Framework
*** Keywords ***
${type} Framework
Should Be Equal ${type} Automation
Robot ${action}
Should Be Equal ${action} uprising
只接受"普通"参数或不接受任何参数的关键字被认为比接受嵌入式参数的关键字匹配更好。例如,如果在上面的示例中添加以下关键字,后一个测试中使用的 Robot Framework 会匹配它,测试就能通过:
*** Keywords ***
Robot Framework
No Operation
在查找最佳匹配之前,Robot Framework 会先检查匹配的关键字中是否有与调用方关键字在同一文件中实现的。如果有,这些关键字会被优先使用。也可以通过库搜索顺序来控制 Robot Framework 在资源和库中查找关键字的顺序。
当多个带嵌入式参数的关键字匹配时自动解决冲突是 Robot Framework 6.0 的新功能。在旧版本中可以使用下面介绍的自定义正则表达式。
使用自定义正则表达式
当调用带嵌入式参数的关键字时,内部使用正则表达式(简称 regexp)进行值匹配。默认逻辑是将名称中的每个参数替换为 .*? 模式,该模式匹配任意字符串并尽可能少地匹配。这种逻辑通常工作得很好,但如前所述,有时关键字会匹配错误的值,有时会出现无法解决的冲突。解决方案是指定自定义正则表达式,确保关键字在特定上下文中只匹配它应该匹配的内容。要使用此功能并完全理解本节的示例,你至少需要了解正则表达式语法的基础知识。
自定义嵌入式参数正则表达式在参数基本名称之后定义,参数名和正则表达式之间用冒号分隔。例如,只应匹配数字的参数可以定义为 ${arg:\d+}。如果需要,自定义模式可以使用内联标志前缀,如 (?i) 用于不区分大小写。
以下示例展示了自定义正则表达式的使用。第一个示例展示了如何在不使用引号的情况下解决前面 Select ${city} ${team} 无法正确匹配 Select Los Angeles Lakers 的问题——通过限制 ${team} 只能包含非空白字符。
*** Test Cases ***
Do not match whitespace characters
Select Chicago Bulls
Select Los Angeles Lakers
Match numbers and characters from set
1 + 2 = 3
53 - 11 = 42
Match either date or literal 'today'
Deadline is 2022-09-21
Deadline is today
Case-insensitive match
Select dog
Select CAT
*** Keywords ***
Select ${city} ${team:\S+}
Log Selected ${team} from ${city}.
${number1:\d+} ${operator:[+-]} ${number2:\d+} = ${expected:\d+}
${result} = Evaluate ${number1} ${operator} ${number2}
Should Be Equal As Integers ${result} ${expected}
Deadline is ${deadline: date:\d{4}-\d{2}-\d{2}|today}
# 上面参数中的 ': date' 部分指定了参数类型。
# 更多信息请参阅参数类型转换的相关章节。
Log Deadline is ${deadline.day}.${deadline.month}.${deadline.year}.
Select ${animal:(?i)cat|dog}
[Documentation] 内联标志 `(?i)` 使模式不区分大小写。
Log Selected ${animal}!
内联标志支持是 Robot Framework 7.2 的新功能。
支持的正则表达式语法
Robot Framework 基于 Python 实现,自然使用 Python 的 re 模块,该模块具有相当标准的正则表达式语法。嵌入式参数完全支持此语法,但 (?...) 格式的正则扩展不能使用。如果正则表达式语法无效,创建关键字将失败,并在测试执行错误中显示相应错误。
转义特殊字符
正则表达式大量使用反斜杠字符(\)来形成特殊序列(如 \d)和转义在正则中有特殊含义的字符(如 \$)。通常在 Robot Framework 数据中反斜杠字符需要用另一个反斜杠转义,但在此上下文中不需要。如果需要在模式中使用字面反斜杠,则必须转义,如 ${path:c:\\temp\\.*}。
模式中可能出现的单独的左右花括号必须转义,如 ${open:\{} 和 ${close:\}},否则 Robot Framework 无法正确解析变量语法。如果花括号是成对的(如 ${digits:\d{2}}),则不需要转义。
在 Robot Framework 3.2 之前,必须转义模式中的所有右花括号,如
${digits:\d{2\}}。此语法在 Robot Framework 3.2 或更新版本中不再支持,使用它的关键字在升级时必须更新。
在 Robot Framework 6.0 之前,在模式中使用字面反斜杠需要双重转义,如
${path:c:\\\\temp\\\\.*}。使用字面反斜杠的模式在升级时需要更新。
在自定义嵌入式参数正则表达式中使用变量
使用带自定义正则表达式的嵌入式参数时,通过变量指定值仅在变量匹配整个嵌入式参数时有效,如果变量只是部分内容则无效。例如,下面的第一个测试成功,因为变量 ${DATE} 是独立使用的,但最后一个测试失败,因为 ${YEAR}-${MONTH}-${DAY} 不是单个变量。
*** Variables ***
${DATE} 2011-06-27
${YEAR} 2011
${MONTH} 06
${DAY} 27
*** Test Cases ***
Succeeds
Deadline is ${DATE}
Succeeds without variables
Deadline is 2011-06-27
Fails
Deadline is ${YEAR}-${MONTH}-${DAY}
*** Keywords ***
Deadline is ${deadline:\d{4}-\d{2}-\d{2}}
Should Be Equal ${deadline} 2011-06-27
使用变量的另一个限制是,变量的实际值不会与自定义正则表达式进行匹配。因此关键字可能会被自定义正则不允许的值调用。此行为从 Robot Framework 6.0 开始已弃用,未来将对值进行验证。更多信息请参阅 issue #4462。
嵌入式参数的类型转换
接受嵌入式参数的用户关键字支持 ${name: type} 类型语法的参数转换,与普通用户关键字类似。如果需要自定义模式,可以用额外的冒号分隔,如 ${name: type:pattern}。
*** Test Cases ***
Example
Buy 3 books
Deadline is 2025-05-30
*** Keywords ***
Buy ${quantity: int} books
Should Be Equal ${quantity} ${3}
Deadline is ${deadline: date:\d{4}-\d{2}-\d{2}}
Should Be Equal ${deadline.year} ${2025}
Should Be Equal ${deadline.month} ${5}
Should Be Equal ${deadline.day} ${30}
因为类型分隔符是冒号加空格(如 ${arg: int}),而模式分隔符只是冒号(如 ${arg:\d+}),在只使用类型或只使用模式时通常不会有冲突。唯一的例外是模式以空格开头的情况,此时空格可以转义如 ${arg:\ abc},或添加类型如 ${arg: str: abc}。
用户关键字的参数类型转换是 Robot Framework 7.3 的新功能。
行为驱动开发示例
将参数作为关键字名称的一部分有一个很大的好处:在使用行为驱动风格编写测试时,更容易使用更高层级的句子式关键字。如下例所示,此功能通常与在关键字定义中省略 Given、When 和 Then 前缀的特性配合使用:
*** Test Cases ***
Add two numbers
Given I have Calculator open
When I add 2 and 40
Then result should be 42
Add negative numbers
Given I have Calculator open
When I add 1 and -2
Then result should be -1
*** Keywords ***
I have ${program} open
Start Program ${program}
I add ${number 1} and ${number 2}
Input Number ${number 1}
Push Button +
Input Number ${number 2}
Push Button =
Result should be ${expected}
${result} = Get Result
Should Be Equal ${result} ${expected}
Robot Framework 的嵌入式参数功能受到了流行 BDD 工具 Cucumber 中 step definitions 的启发。
用户关键字返回值
与库关键字类似,用户关键字也可以返回值。使用 Robot Framework 5.0 或更新版本时,推荐使用原生 RETURN 语句。旧的 [Return] 设置在 Robot Framework 7.0 中已弃用,BuiltIn 关键字 Return From Keyword 和 Return From Keyword If 也被视为已弃用。
无论采用哪种方式返回值,都可以将其赋值给测试用例和其他用户关键字中的变量。
使用 RETURN 语句
推荐的返回值方式是使用 RETURN 语句。它接受可选的返回值,可以与 IF 和内联 IF 结构一起使用。通过示例最容易理解其用法:
*** Keywords ***
Return One Value
[Arguments] ${arg}
[Documentation] 无条件返回一个值。
... 注意 RETURN 之后的关键字不会执行。
${value} = Convert To Upper Case ${arg}
RETURN ${value}
Fail Not executed
Return Three Values
[Documentation] 返回多个值。
RETURN a b c
Conditional Return
[Arguments] ${arg}
[Documentation] 条件返回。
Log Before
IF ${arg} == 1
Log Returning!
RETURN
END
Log After
Find Index
[Arguments] ${test} ${items}
[Documentation] 包含 FOR 循环、内联 IF 和 @{list} 变量语法的高级示例。
FOR ${index} ${item} IN ENUMERATE @{items}
IF $item == $test RETURN ${index}
END
RETURN ${-1}
如果想自己测试上述示例,可以配合以下测试用例使用:
*** Settings ***
Library String
*** Test Cases ***
One return value
${ret} = Return One Value argument
Should Be Equal ${ret} ARGUMENT
Multiple return values
${a} ${b} ${c} = Return Three Values
Should Be Equal ${a}, ${b}, ${c} a, b, c
Conditional return
Conditional Return 1
Conditional Return 2
Advanced
@{list} = Create List foo bar baz
${index} = Find Index bar ${list}
Should Be Equal ${index} ${1}
${index} = Find Index non existing ${list}
Should Be Equal ${index} ${-1}
RETURN 语法区分大小写,与 IF 和 FOR 类似。
RETURN 是 Robot Framework 5.0 的新功能。如需支持旧版本,请使用下面介绍的方法。
使用 [Return] 设置
[Return] 设置定义关键字执行完毕后应返回的内容。虽然推荐将其放在关键字末尾(逻辑上归属的位置),但其位置不影响使用方式。
[Return] 设置的固有局限性是无法条件性地使用。因此只有前面 RETURN 语句示例中的前两个可以用 [Return] 创建。
*** Keywords ***
Return One Value
[Arguments] ${arg}
${value} = Convert To Upper Case ${arg}
[Return] ${value}
Return Three Values
[Return] a b c
[Return]设置在 Robot Framework 7.0 中已弃用,应改用 RETURN 语句。如果需要支持不支持 RETURN 的旧版 Robot Framework,可以使用下一节讨论的特殊关键字。
使用特殊关键字返回值
BuiltIn 关键字 Return From Keyword 和 Return From Keyword If 允许在关键字中间有条件地返回。它们也接受可选的返回值,处理方式与 RETURN 语句和 [Return] 设置完全相同。
RETURN 语句的引入使这些关键字变得多余。下面的示例包含与前面 RETURN 示例相同的关键字,但更加冗长:
*** Keywords ***
Return One Value
[Arguments] ${arg}
${value} = Convert To Upper Case ${arg}
Return From Keyword ${value}
Fail Not executed
Return Three Values
Return From Keyword a b c
Conditional Return
[Arguments] ${arg}
Log Before
IF ${arg} == 1
Log Returning!
Return From Keyword
END
Log After
Find Index
[Arguments] ${test} ${items}
FOR ${index} ${item} IN ENUMERATE @{items}
Return From Keyword If $item == $test ${index}
END
Return From Keyword ${-1}
这些关键字实际上已弃用,除非需要支持 Robot Framework 5.0 之前的版本,否则应使用 RETURN 语句。目前使用这些关键字时尚无可见的弃用警告,但未来将添加明显的弃用警告并最终移除。
用户关键字的 setup 和 teardown
用户关键字可以像测试一样拥有 setup 和 teardown,通过 [Setup] 和 [Teardown] 设置项直接在关键字中指定。与测试不同的是,无法为某个文件中的所有关键字指定公共的 setup 或 teardown。
setup 和 teardown 始终是单个关键字,但它们本身可以是执行多个关键字的用户关键字。可以将其指定为变量,使用特殊值 NONE(不区分大小写)等同于不设置 setup 或 teardown。
用户关键字的 setup 与关键字内部的第一个关键字没有太大区别。唯一的功能差异是 setup 可以指定为变量,但能够明确地将某个关键字标记为 setup 也有其用处。
用户关键字的 teardown 与测试 teardown 完全一样,即使用户关键字失败也会执行。因此在需要在关键字结束时执行某些操作(无论其状态如何)时非常有用。为确保所有清理活动都能完成,用户关键字 teardown 默认启用失败后继续运行模式,与测试 teardown 相同。
*** Keywords ***
Setup and teardown
[Setup] Log New in RF 7!
Do Something
[Teardown] Log Old feature.
Using variables
[Setup] ${SETUP}
Do Something
[Teardown] ${TEARDOWN}
用户关键字的 setup 是 Robot Framework 7.0 的新功能。
私有用户关键字
用户关键字可以通过添加特殊标签 robot:private 来表明它们仅应在创建它们的文件中使用:
*** Keywords ***
Public Keyword
Private Keyword
Private Keyword
[Tags] robot:private
No Operation
使用 robot:private 标签并不会完全阻止在创建文件之外使用该关键字,但此类使用会触发警告。如果存在同名的公有和私有关键字,将使用公有关键字,但这种情况也会触发警告。
私有关键字会包含在 Libdoc 创建的 spec 文件中,但不会出现在其 HTML 输出文件中。
私有用户关键字是 Robot Framework 6.0 的新功能。
递归
用户关键字可以直接或间接地调用自身。这种递归使用是允许的,只要递归在超过递归限制之前终止(通常基于某个条件)。该限制的存在是为了防止无限递归导致执行崩溃。
Robot Framework 的递归检测机制会检查当前递归层级是否接近底层 Python 进程的递归限制。如果足够接近,将不允许启动新的关键字或控制结构,执行将失败。
Python 的默认递归限制为 1000 个栈帧,实际上这意味着大约可以启动 140 个关键字或控制结构。如果不够用,可以通过 sys.setrecursionlimit() 函数提高 Python 的递归限制。正如该函数的文档所说,应谨慎操作,因为过高的限制可能导致崩溃。
在 Robot Framework 7.2 之前,递归限制硬编码为 100 个启动的关键字或控制结构。