Robot Framework 新版教程 - 基本用法
(Robot Framework 7.x 教程, Part 12)
基本用法
Robot Framework 测试用例(test case)从命令行执行,默认的最终结果是一个 XML 格式的输出文件、一个 HTML 报告和一个日志。执行之后,输出文件可以使用 Rebot 工具进行合并和其他后处理。
启动测试执行
概要
robot [options] data
python -m robot [options] data
python path/to/robot/ [options] data
执行通常使用安装过程中创建的 robot 命令来启动。也可以使用所选的 Python 解释器执行已安装的 robot 模块。当 Robot Framework 被安装在多个 Python 版本下时,这种方式尤其方便。如果你知道已安装的 robot 目录所在的位置,也可以用 Python 来执行它。
无论使用哪种执行方式,待执行的测试数据的路径作为命令之后的参数给出。此外,还可以使用各种命令行选项来改变测试执行或生成的输出。
指定待执行的测试数据
Robot Framework 测试用例创建在文件和目录中,通过将文件或目录的路径提供给所选的运行脚本来执行。路径可以是绝对路径,也可以是相对于测试执行目录的相对路径(更常见)。给定的文件或目录会创建顶层测试套件(test suite),默认情况下其名称来自文件或目录名。下面的示例展示了不同的执行方式。注意,在这些示例以及本节的其他示例中,只使用了 robot 脚本,但其他执行方式也可以类似使用。
robot tests.robot
robot path/to/my_tests/
robot c:\robot\tests.robot
当执行一个目录时,所有以点(
.)或下划线(_)开头的文件和目录都会被忽略,并且默认只执行扩展名为.robot的文件。更多细节参见选择待解析的文件一节。
也可以一次给出多个测试用例文件或目录的路径,用空格分隔。这种情况下,Robot Framework 会自动创建顶层测试套件,指定的文件和目录成为其子测试套件。创建的测试套件名称由子套件名称用 & 符号和空格连接而成。例如,下面第一个示例中的顶层套件名称是 My Tests & Your Tests。这种自动创建的名称通常很长且复杂。在大多数情况下,最好使用 --name 选项来覆盖它,如下面第二个示例所示:
robot my_tests.robot your_tests.robot
robot --name Example path/to/tests/pattern_*.robot
从 Robot Framework 6.1 开始,也可以为自动创建的顶层套件定义一个测试套件初始化文件。初始化文件的路径与测试用例文件的给出方式类似:
robot __init__.robot my_tests.robot other_tests.robot
使用命令行选项
Robot Framework 提供了许多命令行选项,可用于控制测试用例的执行方式和生成的输出。本节解释选项语法以及实际存在的选项。它们的使用方式在本章的其他部分讨论。
使用选项
使用选项时,它们必须始终放在运行脚本和数据源之间。例如:
robot -L debug my_tests.robot
robot --include smoke --variable HOST:10.0.0.42 path/to/tests/
短选项和长选项
选项总是有一个长名称,如 --name,最常用的选项也有一个短名称,如 -N。此外,长选项可以缩写,只要缩写后仍然是唯一的。例如,--logle DEBUG 可以工作,而 --lo log.html 不行,因为前者只匹配 --loglevel,但后者匹配多个选项。短选项和缩写选项在手动执行测试用例时很实用,但在启动脚本中建议使用长选项,因为它们更容易理解。
长选项名称是大小写不敏感和连字符不敏感的,这方便以易读的格式书写选项名称。例如,--SuiteStatLevel 和 --suite-stat-level 等价于 --suitestatlevel,但更易读。
长选项连字符不敏感是 Robot Framework 6.1 的新特性。
设置选项值
大多数选项需要一个值,该值在选项名称之后给出。短选项和长选项都接受用空格分隔的值,如 --include tag 或 -i tag。对于长选项,分隔符也可以是等号,例如 --include=tag,对于短选项,分隔符可以省略,如 -itag。
某些选项可以指定多次。例如,--variable VAR1:value --variable VAR2:another 设置两个变量。如果只接受一个值的选项被使用了多次,则最后给出的值生效。
禁用不接受值的选项
不接受值的选项可以通过再次使用相同选项并添加或去掉 no 前缀来禁用。最后一个选项优先,无论选项被使用了多少次。例如,--dryrun --dryrun --nodryrun --nostatusrc --statusrc 不会激活 dry-run 模式,并且会返回正常的状态返回码。
简单模式
许多命令行选项接受简单模式作为参数。这些类 glob 模式按照以下规则匹配:
*匹配任意字符串,包括空字符串。?匹配任意单个字符。[abc]匹配括号中的一个字符。[!abc]匹配不在括号中的一个字符。[a-z]匹配括号中范围内的一个字符。[!a-z]匹配不在括号中范围内的一个字符。- 与通常的 glob 模式不同,路径分隔符
/和\以及换行符\n可以被上述通配符匹配。 - 除非另有说明,模式匹配是大小写、空格和下划线不敏感的。
示例:
--test Example* # 匹配名称以 'Example' 开头的测试。
--test Example[1-2] # 匹配测试 'Example1' 和 'Example2'。
--include f?? # 匹配带有以 'f' 开头且长度为三个字符的 tag 的测试。
上面所有示例中的匹配都是大小写、空格和下划线不敏感的。例如,第二个示例也会匹配名为 example 1 的测试。
如果被匹配的文本恰好包含某些通配符字符,且需要按字面意思匹配它们,可以使用 [...] 语法。模式 [*] 匹配字面量 * 字符,[?] 匹配 ?,[[] 匹配 [。单独的 [ 和 ] 不需要转义。
对
[abc]和[!a-z]等括号的支持是 Robot Framework 3.1 的新特性。
Tag 模式
大多数与 tag 相关的选项接受 tag 模式作为参数。它们支持与简单模式相同的通配符(如 examp??、ex*le),但它们还支持下面介绍的 AND、OR 和 NOT 运算符。这些运算符可用于将两个或更多单独的 tag 或模式组合在一起。
AND 或 &
当所有单独的模式都匹配时,整个模式匹配。AND 和 & 等价:
--include fooANDbar # 匹配包含 tag 'foo' 和 'bar' 的测试。
--exclude xx&yy&zz # 匹配包含 tag 'xx'、'yy' 和 'zz' 的测试。
OR
当任意单独的模式匹配时,整个模式匹配:
--include fooORbar # 匹配包含 tag 'foo' 或 tag 'bar' 的测试。
--exclude xxORyyORzz # 匹配包含 tag 'xx'、'yy' 或 'zz' 中任意一个的测试。
NOT
当左侧的模式匹配但右侧的不匹配时,整个模式匹配。如果使用多次,第一个 NOT 之后的所有模式都不能匹配:
--include fooNOTbar # 匹配包含 tag 'foo' 但不包含 tag 'bar' 的测试。
--exclude xxNOTyyNOTzz # 匹配包含 tag 'xx' 但不包含 tag 'yy' 或 tag 'zz' 的测试。
模式也可以以 NOT 开头,此时如果 NOT 之后的模式不匹配,则整个模式匹配:
--include NOTfoo # 匹配不包含 tag 'foo' 的测试
--include NOTfooANDbar # 匹配不同时包含 tag 'foo' 和 'bar' 的测试
上述运算符也可以一起使用。运算符优先级从高到低为 AND、OR 和 NOT:
--include xANDyORz # 匹配包含 tag 'x' 和 'y' 的测试,或包含 tag 'z' 的测试。
--include xORyNOTz # 匹配包含 tag 'x' 或 'y' 但不包含 tag 'z' 的测试。
--include xNOTyANDz # 匹配包含 tag 'x' 但不同时包含 tag 'y' 和 'z' 的测试。
虽然 tag 匹配本身是大小写不敏感的,但所有运算符都是大小写敏感的,必须用大写字母书写。如果 tag 本身恰好包含大写的 AND、OR 或 NOT,需要使用小写字母来指定,以避免意外的运算符用法:
--include port # 大小写不敏感地匹配包含 tag 'port' 的测试
--include PORT # 大小写不敏感地匹配包含 tag 'P' 或 'T' 的测试
--exclude handoverORportNOTnotification
ROBOT_OPTIONS 和 REBOT_OPTIONS 环境变量
环境变量 ROBOT_OPTIONS 和 REBOT_OPTIONS 可分别用于为测试执行和结果后处理指定默认选项。选项及其值必须定义为以空格分隔的列表,它们被放置在命令行上任何显式选项之前。这些环境变量的主要用途是为某些选项设置全局默认值,以避免每次运行测试或使用 Rebot 时重复指定。
export ROBOT_OPTIONS="--outputdir results --tagdoc 'mytag:Example doc with spaces'"
robot tests.robot
export REBOT_OPTIONS="--reportbackground blue:red:yellow"
rebot --name example output.xml
测试结果
命令行输出
测试执行中最直观的输出是在命令行中显示的内容。所有已执行的测试套件和测试用例及其状态都会实时显示在那里。下面的示例展示了执行一个只有两个测试用例的简单测试套件的输出:
==============================================================================
Example test suite
==============================================================================
First test :: Possible test documentation | PASS |
------------------------------------------------------------------------------
Second test | FAIL |
Error message is displayed here
==============================================================================
Example test suite | FAIL |
2 tests, 1 passed, 1 failed
==============================================================================
Output: /path/to/output.xml
Report: /path/to/report.html
Log: /path/to/log.html
每当测试用例中的一个顶层关键字(keyword)结束时,控制台上也会显示一个通知。如果关键字通过则显示绿色的点,如果失败则显示红色的 F。这些标记写在行尾,当测试本身结束时会被测试状态覆盖。如果控制台输出被重定向到文件,则禁用写入标记。
生成的输出文件
命令行输出非常有限,通常需要单独的输出文件来查看测试结果。如上面的示例所示,默认生成三个输出文件。第一个是 XML 格式的,包含关于测试执行的所有信息。第二个是更高层次的报告,第三个是更详细的日志文件。这些文件和其他可能的输出文件在不同的输出文件一节中有更详细的讨论。
返回码
运行脚本使用返回码向运行它们的系统传达整体执行状态。当执行成功启动且没有测试失败时,返回码为零。所有可能的返回码在下表中说明。
| 返回码 | 说明 |
|---|---|
| 0 | 所有测试通过。 |
| 1-249 | 返回失败的测试数量。 |
| 250 | 250 个或更多失败。 |
| 251 | 打印了帮助或版本信息。 |
| 252 | 无效的数据或命令行选项。 |
| 253 | 执行被用户停止。 |
| 255 | 意外的内部错误。 |
返回码在执行后应始终容易获取,这使得自动确定整体执行状态变得简单。例如,在 Bash shell 中返回码保存在 $? 变量中,在 Windows 中保存在 %ERRORLEVEL% 变量中。如果你使用某些外部工具来运行测试,请查阅其文档了解如何获取返回码。
可以使用 --nostatusrc 命令行选项将返回码设置为零,无论执行状态如何。这在某些场景下可能很有用,例如在持续集成服务器中,在确定整体执行状态之前需要对结果进行后处理。
相同的返回码也适用于 Rebot。
在获取帮助和版本信息时,
--nostatusrc选项仅在 Robot Framework 7.4 及更新版本中生效。
执行过程中的错误和警告
在测试执行过程中,可能会出现意外问题,如导入库(library)或资源文件(resource file)失败,或者关键字被标记为废弃。根据严重程度,这些问题被分类为错误或警告,并写入控制台(使用标准错误流),在日志文件中单独的 Test Execution Errors 区域显示,也写入 Robot Framework 自己的系统日志。通常这些错误和警告由 Robot Framework 自身生成,但库也可以记录错误和警告。下面的示例展示了错误和警告在日志文件中的样子。
| 时间 | 级别 | 消息 |
|---|---|---|
| 20090322 19:58:42.528 | ERROR | Error in file '/home/robot/tests.robot' in table 'Setting' in element on row 2: Resource file 'resource.robot' does not exist |
| 20090322 19:58:43.931 | WARN | Keyword 'SomeLibrary.Example Keyword' is deprecated. Use keyword Other Keyword instead. |
参数文件
参数文件(argument file)允许将所有或部分命令行选项和参数放入外部文件中读取。这避免了命令行上某些字符的问题。如果需要大量选项或参数,参数文件也能防止命令行上使用的命令变得过长。
参数文件通过 --argumentfile (-A) 选项启用,可以和其他命令行选项一起使用。
与其他长命令行选项不同,
--argumentfile不能以缩写形式给出,如--argumentf。
参数文件语法
参数文件可以包含命令行选项和待执行数据的路径,每行一个选项或数据源。短选项和长选项都受支持,但在此场景下建议使用长选项,因为它们更容易理解。参数文件可以包含任何字符而无需转义(escape),但行首和行尾的空格会被忽略。此外,空行和以井号(#)开头的行会被忽略:
--doc This is an example (where "special characters" are ok!)
--metadata X:Value with spaces
--variable NAME:Hello, world!
# 这是一条注释
path/to/my/tests
在上面的示例中,选项和其值之间的分隔符(separator)是一个空格。也可以使用等号(=)或任意数量的空格。例如,以下三行是等价的:
--name An Example
--name=An Example
--name An Example
如果参数文件包含非 ASCII 字符,必须使用 UTF-8 编码保存。参数文件可以使用任何扩展名。通常 .txt 就够用了,但也可以使用自定义扩展名如 .args 来区分参数文件和普通文本文件。
展开环境变量
从 Robot Framework 7.4 开始,可以在参数文件中使用环境变量,并在文件被处理之前进行替换。出于向后兼容的原因,此功能默认未启用,但可以通过在参数文件的第一行添加 # expandvars: true 来轻松启用。该功能将来可能会默认启用,目前也可以通过 # expandvars: false 来显式禁用。
环境变量可以使用 $NAME 和 ${NAME} 格式。此外还支持默认值,如 ${NAME=default}。如果需要字面量的美元符号,可以通过双写来转义,如 $$not_var:
# expandvars: true
--name $NAME
--doc ${NAME}v${VERSION}
--metadata Default:${META=default value}
--metadata Escape:$$100
环境变量不仅限于选项值。它们也可以包含选项名称、同时包含名称和值,利用注释字符甚至可以实现条件选项:
# expandvars: true
--${NAME} ${VALUE}
${NAME_AND_VALUE}
${COND1=} --metadata COND1:This is enabled by default. Set 'COND1' to '#' to disable.
${COND2=#} --metadata COND2:This is disabled by default. Set 'COND2' to '' to enable.
环境变量名称是大小写敏感的,只能包含 ASCII 字母、数字和下划线,且不能以数字开头。使用不存在的变量或无效的变量名会导致错误。
使用参数文件
参数文件可以单独使用(包含所有选项和测试数据路径),也可以与其他选项和路径一起使用。当参数文件与其他参数一起使用时,其内容被放置到原始参数列表中参数文件选项所在的位置。这意味着参数文件中的选项可以覆盖它之前的选项,而它的选项也可以被它之后的选项覆盖。可以多次使用 --argumentfile 选项,甚至可以递归使用:
robot --argumentfile all_options_and_arguments.txt
robot --argumentfile defaults.args --name Example tests.robot
robot -A first.txt -A second.txt -A third.txt tests.robot
从标准输入读取参数文件
特殊的参数文件名 STDIN 可用于从标准输入流而非文件中读取参数。这在使用脚本生成参数时很有用:
generate_arguments.sh | robot --argumentfile STDIN
generate_arguments.sh | robot --name Example --argumentfile STDIN tests.robot
获取帮助和版本信息
无论是执行测试还是后处理输出,都可以使用 --help (-h) 选项获取命令行帮助。此帮助文本提供版本信息、简短的概述以及可用命令行选项的说明。
也可以使用 --version 选项只获取版本信息。此信息还包含 Python 版本和平台类型:
$ robot --version
Robot Framework 7.4 (Python 3.14.0 on linux)
C:\>rebot --version
Rebot 7.3.1 (Python 3.13.7 on win32)
当帮助或版本信息被打印到控制台时,执行默认以特殊的返回码 251 退出。从 Robot Framework 7.4 开始,可以通过使用 --nostatusrc 选项将返回码改为零,如 robot --version --nostatusrc。
创建启动脚本
测试用例通常由持续集成系统或其他某种机制自动执行。在这种情况下,需要一个脚本来启动测试执行,可能还需要对输出进行某种后处理。在手动运行测试时,类似的脚本也很有用,特别是当需要大量命令行选项或设置测试环境比较复杂时。
在类 UNIX 环境中,shell 脚本提供了一种简单但强大的机制来创建自定义启动脚本。Windows 批处理文件也可以使用,但功能更有限,通常也更复杂。一种跨平台的替代方案是使用 Python 或其他高级编程语言。无论使用哪种语言,建议使用长选项名称,因为它们比短名称更容易理解。
Shell 脚本示例
在此示例中,login 目录中的相同 web 测试使用不同的浏览器执行,之后使用 Rebot 合并结果。脚本也接受命令行选项本身,并使用便捷的 $* 变量将它们转发给 robot 命令:
#!/bin/bash
robot --name Firefox --variable BROWSER:Firefox --output out/fx.xml --log none --report none $* login
robot --name IE --variable BROWSER:IE --output out/ie.xml --log none --report none $* login
rebot --name Login --outputdir out --output login.xml out/fx.xml out/ie.xml
批处理文件示例
用批处理文件实现上面的 shell 脚本示例也不太复杂。注意,批处理文件的参数可以使用 %* 转发给执行的命令:
@echo off
robot --name Firefox --variable BROWSER:Firefox --output out\fx.xml --log none --report none %* login
robot --name IE --variable BROWSER:IE --log none --output out\ie.xml --report none %* login
rebot --name Login --outputdir out --output login.xml out\fx.xml out\ie.xml
在 Robot Framework 3.1 之前,
robot和rebot命令在 Windows 上是以批处理文件实现的,在另一个批处理文件中使用它们需要在整个命令前加上call。
Python 示例
当启动脚本变得更复杂时,使用 shell 脚本或批处理文件实现就不那么方便了。当需要两种变体且相同的逻辑需要实现两次时尤其如此。在这种情况下,切换到 Python 通常更好。可以使用 subprocess 模块从 Python 执行 Robot Framework,但使用 Robot Framework 自己的编程 API 通常更方便。最容易使用的 API 是 robot.run_cli 和 robot.rebot_cli,它们接受与 robot 和 rebot 命令相同的命令行参数。
以下示例实现了与之前 shell 脚本和批处理文件示例相同的逻辑。在 Python 中,脚本本身的参数可以通过 sys.argv 获取:
#!/usr/bin/env python
import sys
from robot import run_cli, rebot_cli
common = ['--log', 'none', '--report', 'none'] + sys.argv[1:] + ['login']
run_cli(['--name', 'Firefox', '--variable', 'BROWSER:Firefox', '--output', 'out/fx.xml'] + common, exit=False)
run_cli(['--name', 'IE', '--variable', 'BROWSER:IE', '--output', 'out/ie.xml'] + common, exit=False)
rebot_cli(['--name', 'Login', '--outputdir', 'out', 'out/fx.xml', 'out/ie.xml'])
exit=False是必需的,因为默认情况下run_cli会以正确的返回码退出系统。rebot_cli也会这样做,但在上面的示例中这是可以接受的。
使 .robot 文件可执行
在类 UNIX 操作系统上,可以通过给 .robot 文件赋予执行权限并添加 shebang 来使其可执行,如下例所示:
#!/usr/bin/env robot
*** Test Cases ***
Example
Log to console Executing!
如果上述内容在 example.robot 文件中,并且该文件是可执行的,则可以像下面这样从命令行执行它。从 Robot Framework 3.2 开始,单独执行的文件可以有任何扩展名或没有扩展名,因此如果文件仅命名为 example 也同样有效。
./example.robot
这个技巧在执行目录时不起作用,但在执行单个文件时可能很方便。它在自动化任务时可能比自动化测试更常用。
调试问题
测试用例可能因为被测系统工作不正确而失败(此时测试发现了一个 bug),或者因为测试本身有问题。解释失败原因的错误消息显示在命令行输出和报告文件中,有时仅靠错误消息就足以定位问题。然而更多情况下,需要日志文件,因为它们还包含其他日志消息并显示哪个关键字实际失败了。
当失败由被测应用引起时,错误消息和日志消息应该足以理解原因。如果不够,说明测试库没有提供足够的信息,需要增强。在这种情况下,如果可能的话,手动运行相同的测试也可能揭示更多关于问题的信息。
由测试用例本身或其使用的关键字引起的失败有时可能难以调试。如果错误消息告诉你关键字使用了错误数量的参数,修复问题显然很容易,但如果关键字缺失或以意外方式失败,找到根本原因可能更困难。查找更多信息的第一个地方是日志文件中的执行错误区域。例如,关于测试库导入失败的错误可能很好地解释了为什么测试因缺少关键字而失败。
如果日志文件默认没有提供足够的信息,可以使用更低的日志级别来执行测试。例如,显示代码中失败位置的回溯信息使用 DEBUG 级别记录,当问题出在某个库关键字中时,这些信息非常有价值。
记录的回溯信息不包含 Robot Framework 自身内部方法的信息。如果你怀疑错误是由框架中的 bug 引起的,可以通过将环境变量 ROBOT_INTERNAL_TRACES 设置为任何非空值来启用显示内部跟踪。
如果日志文件仍然没有足够的信息,启用系统日志并查看它提供的信息是个好主意。也可以在测试用例中添加一些关键字来查看正在发生什么。BuiltIn 库的 Log 和 Log Variables 关键字特别有用。如果其他方法都不行,总是可以从邮件列表或其他地方寻求帮助。
使用 Python 调试器(pdb)
也可以使用 Python 标准库中的 pdb 模块来设置断点并交互式调试正在运行的测试。通常通过插入以下代码来调用 pdb:
import pdb; pdb.set_trace()
在你想要进入调试器的位置,但这在 Robot Framework 中无法正常工作,因为标准输出流在关键字执行期间被重定向了。可以在 Python 库中使用以下代码替代:
import sys, pdb; pdb.Pdb(stdout=sys.__stdout__).set_trace()
或者直接在测试用例中使用:
Evaluate pdb.Pdb(stdout=sys.__stdout__).set_trace() modules=sys, pdb