Robot Framework 新版教程 - 测试执行
(Robot Framework 7.x 教程, Part 13)
测试执行
本节描述从解析后的测试数据创建的测试套件(test suite)结构是如何执行的,测试状态是如何确定的,在出现失败时如何继续执行测试用例(test case),以及如何优雅地停止整个测试执行。
执行流程
被执行的套件和测试
测试用例总是在测试套件中执行。从套件文件创建的测试套件直接包含测试,而从目录创建的套件则包含子测试套件,这些子套件要么包含测试,要么包含它们自己的子套件。默认情况下,被执行套件中的所有测试都会运行,但可以使用 --test、--suite、--include 和 --exclude 选项来选择测试。不包含测试的套件会被忽略。
执行从顶层测试套件开始。如果该套件包含测试,它们将逐个执行;如果包含子套件,则按深度优先的顺序递归执行。当执行单个测试用例时,它包含的关键字(keyword)按顺序运行。正常情况下,如果任何关键字失败,当前测试的执行就会终止,但也可以在失败后继续执行。具体的执行顺序以及 setup 和 teardown 如何影响执行将在后续章节讨论。
Setup 和 teardown
Setup 和 teardown 可以在测试套件、测试用例和用户关键字层级使用。
Suite setup
如果测试套件有 setup,它会在该套件的测试和子套件之前执行。如果 suite setup 通过,测试执行正常继续。如果它失败,该套件及其子套件中包含的所有测试用例都会被标记为失败。子测试套件中的测试以及可能存在的 suite setup 和 teardown 都不会被执行。
Suite setup 通常用于设置测试环境。由于 suite setup 失败时测试不会运行,因此很容易利用 suite setup 来验证环境是否处于可以执行测试的状态。
Suite teardown
如果测试套件有 teardown,它会在该套件的所有测试用例和子套件之后执行。无论测试状态如何,suite teardown 都会执行,即使匹配的 suite setup 失败也是如此。如果 suite teardown 失败,该套件中的所有测试在报告和日志中都会被标记为失败。
Suite teardown 主要用于在执行结束后清理测试环境。为了确保所有这些任务都能完成,teardown 中使用的所有关键字都会被执行,即使其中一些失败了。
Test setup
可能存在的 test setup 会在测试用例的关键字之前执行。如果 setup 失败,关键字不会被执行。Test setup 的主要用途是为特定的测试用例设置环境。
Test teardown
可能存在的 test teardown 会在测试用例执行之后执行。无论测试状态如何它都会执行,即使 test setup 失败也是如此。
与 suite teardown 类似,test teardown 主要用于清理活动。它们也会被完整执行,即使其中一些关键字失败了。
用户关键字 setup
用户关键字(user keyword)的 setup 在关键字主体之前执行。如果 setup 失败,主体不会被执行。关键字 setup 与关键字主体中的第一个关键字之间没有太大区别。
用户关键字 setup 是 Robot Framework 7.0 中的新功能。
用户关键字 teardown
用户关键字的 teardown 在关键字执行完毕后运行,无论状态如何。用户关键字 teardown 会被完整执行,即使其中一些关键字失败了。
执行顺序
测试套件中的测试用例按照它们在测试用例文件中定义的顺序执行。高层测试套件中的子测试套件按照文件名或目录名的字母顺序(不区分大小写)执行。如果从命令行给出了多个文件和/或目录,它们按给出的顺序执行。
如果需要在目录内使用特定的测试套件执行顺序,可以在文件和目录名中添加 01 和 02 这样的前缀。如果这些前缀与套件基本名称之间用两个下划线分隔,则它们不会包含在生成的测试套件名称中:
01__my_suite.robot -> My Suite
02__another_suite.robot -> Another Suite
如果套件内子测试套件的字母排序有问题,一个好的解决方法是按所需顺序单独指定它们。这容易导致过长的启动命令,但参数文件允许每行列出一个文件。
也可以使用 --randomize 选项来随机化执行顺序。
测试和套件状态
本节解释测试如何获得 PASS、FAIL 或 SKIP 状态,以及套件状态如何根据测试状态确定。
SKIP 状态是 Robot Framework 4.0 中的新功能。
PASS
如果测试被执行且其包含的关键字都没有失败,测试获得 PASS 状态。
提前通过测试
正常情况下所有关键字都会被执行,但也可以使用 BuiltIn 库的 Pass Execution 和 Pass Execution If 关键字来以 PASS 状态停止执行并且不运行剩余的关键字。
Pass Execution 和 Pass Execution If 在不同情况下的行为如下:
-
当在任何 setup 或 teardown(suite、test 或 keyword)中使用时,这些关键字会通过该 setup 或 teardown。已启动关键字的可能存在的 teardown 会被执行。测试执行或状态不会受到其他影响。
-
当在测试用例中(setup 或 teardown 之外)使用时,这些关键字会通过该特定测试用例。可能存在的 test teardown 和 keyword teardown 会被执行。
-
在使用这些关键字之前发生的可能的可继续失败,以及之后执行的 teardown 中的失败,将导致执行失败。
-
必须给出一个解释消息说明为什么执行被中断,也可以修改测试用例的 tag。更多细节和使用示例,请参见这些关键字的文档。
在测试、setup 或 teardown 的中间传递执行应该谨慎使用。最坏的情况下,它会导致测试跳过所有可能发现被测应用问题的部分。在由于外部因素无法继续执行的情况下,跳过测试通常更安全。
FAIL
测试获得 FAIL 状态最常见的原因是它包含的某个关键字失败了。关键字本身可以通过抛出异常来失败,或者关键字被错误调用。导致失败的其他原因包括语法错误和测试为空。
如果 suite setup 失败,该套件中的测试会被标记为失败而不会运行。如果 suite teardown 失败,测试会被追溯标记为失败。
SKIP
从 Robot Framework 4.0 开始,测试除了 PASS 和 FAIL 外还可以获得 SKIP 状态。有多种不同的方式可以获得此状态。
执行前跳过
命令行选项 --skip 可用于跳过指定的测试而完全不运行它们。它基于 tag 工作,并支持 tag 模式,如 examp?? 和 tagANDanother。如果多次使用,所有匹配任何指定 tag 或 tag 模式的测试都会被跳过:
--skip require-network
--skip windowsANDversion9?
--skip python2.* --skip python3.[0-6]
测试也可以通过给测试打上 robot:skip 保留 tag 来跳过。这个 tag 也可以使用变量设置,从而允许在执行期间动态跳过测试。
*** Variables ***
${SKIP} robot:skip
*** Test Cases ***
Literal
[Documentation] 无条件跳过。
[Tags] robot:skip
Log This is not executed
As variable
[Documentation] 除非 ${SKIP} 被设置为其他值,否则跳过。
[Tags] ${SKIP}
Log This is not executed by default
--skip 和 --exclude 的区别在于,后者会将测试完全从执行中排除,它们不会出现在日志和报告中。前者会将测试包含在内,但不实际执行,并且它们会在日志和报告中可见。
robot:skip是 Robot Framework 5.0 中的新功能。
对用于跳过的 tag 使用变量的支持是 Robot Framework 7.2 中的新功能。
在执行期间动态跳过
测试可以通过多种方式在执行期间获得 SKIP 状态:
-
在测试用例的任何地方(包括 setup 或 teardown)使用 BuiltIn 库的
Skip关键字。使用Skip关键字有两个效果:测试获得 SKIP 状态,并且测试的其余部分不会被执行。但如果测试有 teardown,teardown 仍会运行。 -
使用 BuiltIn 库的
Skip If关键字,它接受一个条件,如果条件为真则跳过测试。 -
如果 suite setup 通过上述任何方式被跳过,套件中的所有测试都会被跳过而不执行。
-
如果 suite teardown 被跳过,所有测试将被追溯标记为已跳过。
自动跳过失败的测试
命令行选项 --skiponfailure 可用于自动将失败的测试标记为已跳过。它基于 tag 工作,并像上面讨论的 --skip 选项一样支持 tag 模式:
--skiponfailure not-ready
--skiponfailure experimentalANDmobile
从 RF 5.0 开始,保留 tag robot:skip-on-failure 可以作为上述方式的替代来达到同样的效果:
*** Test Cases ***
Example
[Tags] robot:skip-on-failure
Fail this test will be marked as skipped instead of failed
此功能的动机是允许执行尚未准备好的测试,或者测试尚未准备好的功能。这些测试不会失败,而是被标记为已跳过,它们的 tag 可用于将它们与其他可能的已跳过测试区分开来。
从关键性到 SKIP 的迁移
早期的 Robot Framework 版本支持关键性(criticality)概念,允许将测试标记为关键或非关键。默认情况下所有测试都是关键的,但可以使用 --critical 和 --noncritical 选项来配置。关键测试和非关键测试的区别在于,非关键测试在确定已执行测试套件或整个测试运行的最终状态时不会被计入。实际上,测试状态是二维的,一个轴是 PASS 和 FAIL,另一个轴是关键性。
非关键的失败测试在很多方面类似于当前的已跳过测试。由于这些功能相似,而且同时拥有 SKIP 和关键性会产生奇怪的测试状态(如非关键的 SKIP),关键性概念在 Robot Framework 4.0 引入 SKIP 状态时被移除了。关键性的问题在提议移除它的 issue 中有更详细的说明。
关键性概念的主要用例是能够运行尚未准备好的测试,或者测试尚未准备好的功能。这个用例现在由上一节讨论的 skip-on-failure 功能覆盖。
为了简化从关键性到跳过的迁移,旧的 --noncritical 选项在 Robot Framework 4.0 中作为新的 --skiponfailure 的别名工作,旧的 --critical 选项也被保留。这两个旧选项都已被弃用,并在 Robot Framework 5.0 中被移除。
套件状态
套件状态完全根据其包含的测试的状态确定:
- 如果任何测试失败,套件状态为 FAIL。
- 如果没有失败但至少有一个测试通过,套件状态为 PASS。
- 如果所有测试都被跳过或者根本没有测试,套件状态为 SKIP。
继续执行
正常情况下,当任何关键字失败时,测试用例会立即停止。这种行为缩短了测试执行时间,并防止后续关键字在被测系统处于不稳定状态时挂起或引起其他问题。但这有一个缺点,后续关键字通常能提供更多关于系统状态的信息,而且在某些情况下,这些后续关键字实际上会处理所需的清理活动。因此 Robot Framework 提供了多种在出现失败时继续执行的功能。
Teardown 中自动继续执行
为了确保所有清理活动都能得到处理,continue-on-failure 模式在 suite、test 和 keyword 的 teardown 中自动启用。实际上这意味着在 teardown 中,所有层级的所有关键字都会被执行。
如果不需要此行为,可以使用特殊的 robot:stop-on-failure 和 robot:recursive-stop-on-failure tag 来禁用它。
使用模板时所有顶层关键字都会执行
当使用测试模板时,所有顶层关键字都会被执行,以确保所有不同的组合都被覆盖。在这种用法中,继续执行仅限于顶层关键字,在它们内部,如果有不可继续的失败,执行会正常终止。
*** Test Cases ***
Continue with templates
[Template] Should be Equal
this fails
this is run
如果不需要此行为,可以使用特殊的 robot:stop-on-failure 和 robot:recursive-stop-on-failure tag 来禁用它。
来自关键字的特殊失败
测试库关键字使用异常报告失败,可以使用特殊异常告诉 Robot Framework 无论失败都可以继续执行。如何创建这些异常在创建测试库的"可继续失败"章节中有解释。
当测试结束且存在可继续失败时,测试将被标记为失败。如果有多个失败,所有失败都会在最终错误消息中列举:
Several failures occurred:
1) First error message.
2) Second error message.
如果在可继续失败之后发生了正常失败,测试执行也会终止。在这种情况下,所有失败也都会列在最终错误消息中。
来自失败关键字的返回值(可能已赋给变量)始终是 Python 的 None。
Run Keyword And Continue On Failure 关键字
BuiltIn 库的 Run Keyword And Continue On Failure 关键字允许将任何失败转换为可继续失败。这些失败由框架以与上面讨论的来自测试库关键字的可继续失败完全相同的方式处理。
*** Test Cases ***
Example
Run Keyword and Continue on Failure Should be Equal 1 2
Log This is executed but test fails in the end
使用 tag 启用 continue-on-failure
作为测试用例或用户关键字的一部分执行的所有关键字,如果带有 robot:continue-on-failure tag,默认都被视为可继续的。例如,以下两个测试的行为完全相同:
*** Test Cases ***
Test 1
Run Keyword and Continue on Failure Should be Equal 1 2
User Keyword 1
Test 2
[Tags] robot:continue-on-failure
Should be Equal 1 2
User Keyword 2
*** Keywords ***
User Keyword 1
Run Keyword and Continue on Failure Should be Equal 3 4
Log This is executed
User Keyword 2
[Tags] robot:continue-on-failure
Should be Equal 3 4
Log This is executed
这些 tag 也会影响不同控制结构中的 continue-on-failure 模式。例如,下面的测试用例无论 Do Something 关键字是否成功,都会执行它十次:
*** Test Cases ***
Example
[Tags] robot:continue-on-failure
FOR ${index} IN RANGE 10
Do Something
END
在测试用例或用户关键字中设置 robot:continue-on-failure 不会将 continue-on-failure 行为传播到它们调用的用户关键字中。如果需要这种递归行为,可以使用 robot:recursive-continue-on-failure tag。例如,以下示例中的所有关键字都会被执行:
*** Test Cases ***
Example
[Tags] robot:recursive-continue-on-failure
Should be Equal 1 2
User Keyword 1
Log This is executed
*** Keywords ***
User Keyword 1
Should be Equal 3 4
User Keyword 2
Log This is executed
User Keyword 2
Should be Equal 5 6
Log This is executed
在测试用例中设置 robot:continue-on-failure 或 robot:recursive-continue-on-failure 不会改变作为 [Setup] 一部分执行的关键字失败时的行为:测试用例被标记为失败,不会执行测试用例关键字。
robot:continue-on-failure和robot:recursive-continue-on-failuretag 是 Robot Framework 4.1 中的新功能。它们在 Robot Framework 6.0 之前无法与WHILE循环正常工作。
使用 tag 禁用 continue-on-failure
特殊 tag robot:stop-on-failure 和 robot:recursive-stop-on-failure 可用于在需要时禁用 continue-on-failure 模式。它们在使用 tag 启用 continue-on-failure 时有效,也适用于 teardown 和模板:
*** Test Cases ***
Disable continue-in-failure set using tags
[Tags] robot:recursive-continue-on-failure
Keyword
Keyword # 这会被执行
Disable continue-in-failure in teardown
No Operation
[Teardown] Keyword
Disable continue-in-failure with templates
[Tags] robot:stop-on-failure
[Template] Should be Equal
this fails
this is not run
*** Keywords ***
Keyword
[Tags] robot:stop-on-failure
Should be Equal this fails
Should be Equal this is not run
robot:stop-on-failure tag 仅影响使用它的测试用例和用户关键字,不会传播到它们调用的用户关键字,也不会影响它们自己的 teardown。如果需要影响所有被调用用户关键字和 teardown 的递归行为,可以使用 robot:recursive-stop-on-failure tag 代替。如果需要,可以在更低层级的关键字中使用 robot:continue-on-failure 或 robot:recursive-continue-on-failure tag 再次禁用其效果。
robot:stop-on-failure 和 robot:recursive-stop-on-failure tag 不会改变由测试库关键字或 Run Keyword And Continue On Failure 引起的可继续失败的行为。例如,以下示例中两个关键字都会被运行,尽管使用了 robot:stop-on-failure:
*** Test Cases ***
Example
[Tags] robot:stop-on-failure
Run Keyword and Continue on Failure Should be Equal 1 2
Log This is executed regardless the tag
如果在同一个测试或关键字中同时使用了 robot:recursive-stop-on-failure 和 robot:continue-on-failure,在被调用的关键字中如果有失败则停止执行,但在使用这些 tag 的测试或关键字中继续执行。如果在同一个测试或关键字中同时使用了 robot:recursive-continue-on-failure 和 robot:stop-on-failure,在被调用的关键字中如果有失败则继续执行,但在使用这些 tag 的测试或关键字中停止执行。
robot:stop-on-failure和robot:recursive-stop-on-failuretag 是 Robot Framework 6.0 中的新功能。
在同一个测试或关键字中同时使用递归和非递归 tag 是 Robot Framework 7.0 中的新功能。
TRY/EXCEPT
Robot Framework 5.0 引入了原生 TRY/EXCEPT 语法,可用于处理失败:
*** Test Cases ***
Example
TRY
Some Keyword
EXCEPT Expected error message
Error Handler Keyword
END
更多细节请参见单独的 TRY/EXCEPT 语法章节。
BuiltIn 关键字
有多个 BuiltIn 库的关键字可用于执行其他关键字,使得在可能的失败后继续执行:
-
Run Keyword And Expect Error执行一个关键字并期望它以指定的错误消息失败。现在通常推荐使用上述的TRY/EXCEPT语法替代。 -
Run Keyword And Ignore Error执行一个关键字并静默可能的错误。它返回状态以及可能的关键字返回值或错误消息。TRY/EXCEPT语法通常在这种情况下也更好用。 -
Run Keyword And Warn On Failure是Run Keyword And Ignore Error的包装器,如果执行的关键字失败会自动记录一个警告。 -
Run Keyword And Return Status执行一个关键字并根据它是通过还是失败返回布尔值True或False。
优雅地停止测试执行
有时需要在所有测试完成之前停止测试执行,但仍然创建日志和报告。下面解释了实现此目的的不同方式。在所有这些情况下,剩余的测试用例会被标记为失败。
自动标记为失败的测试会获得 robot:exit tag,生成的报告将包含 NOT robot:exit 组合 tag 模式,以便轻松查看哪些测试没有被跳过。注意,发生退出的那个测试不会获得 robot:exit tag。
在 Robot Framework 3.1 之前,这个特殊 tag 被命名为
robot-exit。
按 Ctrl-C
当在运行测试的控制台中按下 Ctrl-C 时,执行会停止。执行会立即停止,但报告和日志仍然会生成。
如果再次按下 Ctrl-C,执行会立即终止,报告和日志不会被创建。
使用信号
在类 UNIX 机器上,可以使用 INT 和 TERM 信号来终止测试执行。这些信号可以从命令行使用 kill 命令发送,发送信号也可以很容易地自动化。
使用关键字
执行也可以由被执行的关键字停止。BuiltIn 库有一个专门的 Fatal Error 关键字用于此目的,自定义关键字在失败时可以使用致命异常。
在第一个测试用例失败时停止
如果使用了选项 --exitonfailure (-X),任何测试失败时整个执行都会立即停止。
使用 robot:exit-on-failure tag 停止
如果失败的测试带有特殊的 robot:exit-on-failure 保留 tag,整个执行会在该测试之后立即停止。
此功能是 Robot Framework 7.2 中的新功能。
在解析或执行错误时停止
Robot Framework 区分由关键字失败引起的失败和由例如无效设置或测试库导入失败引起的错误。默认情况下,这些错误会被报告为测试执行错误,但错误本身不会使测试失败或以其他方式影响执行。然而,如果使用了 --exitonerror 选项,所有此类错误都被视为致命的,执行会停止,剩余测试被标记为失败。对于在执行开始之前就遇到的解析错误,这意味着实际上不会运行任何测试。
使用
ERROR日志级别记录内容也被视为错误,如果使用了--exitonerror选项则会停止执行。
处理 teardown
默认情况下,即使使用上述方法之一停止了测试执行,已经开始的测试和套件的 teardown 仍会被执行。这允许清理活动无论执行如何结束都能运行。
也可以使用 --skipteardownonexit 选项在执行停止时跳过 teardown。例如,当清理任务需要很长时间时,这可能很有用。