FOR循环
在自动化测试中, 将某些操作重复执行若干次是一个很常见的需求. 在Robot Framework中, 测试库中可以有任意形式的循环结构, 大多数时候循环操作本应该就在测试库中实现.
Robot Framework也提供了for循环的语法, 这在重复执行来自不同测试库中的关键字的时候很有用.
for循环既可用于测试用例, 也可以在用户关键字中使用. 除非场景特别简单, 不然还是推荐在用户关键字中使用, 这样可以隐藏for循环带来的复杂度. 基本的for循环语法 FOR item IN sequence
借鉴于Python, 不过其它脚本如Perl也有类似的语法.
普通FOR循环
普通的for循环语法中, 每次迭代都从列表中取一个值赋给变量. 语法以 :FOR
开始, 注意开始的冒号是必需的, 以便和其它普通关键字区分开. 跟在后面单元格中的是循环变量, 接下来的格子则必须是 IN
, 后面的格子(可能是多个)里则包含的是待迭代的值. 这些值中可以包含 变量, 包括 列表变量.
for循环中使用的关键字跟在下面的行中, 必须向右缩进一格. 当使用的是 纯文本格式, 缩进单元格必须使用 反斜杠转义, 而其它的数据格式则只需要保持空白就行. for循环结束于正常缩进(即不再缩进)的行, 或者是整个表格的结尾.
- *** Test Cases ***
- Example 1
- :FOR ${animal} IN cat dog
- \ Log ${animal}
- \ Log 2nd keyword
- Log Outside loop
- Example 2
- :FOR ${var} IN one two
- ... ${3} four ${last}
- \ Log ${var}
上面 Example 1 将迭代执行两次, 第一次循环变量 ${animal}
被赋值 cat
, 接下来是 dog
. 循环体包含了两次 Log 关键字调用. 第二个例子中, 循环值 分成了多行, 循环迭代了5次.
在for循环中使用 列表变量 更方便. 如下面的例子, @{ELEMENTS}
是任意长度的列表, 每次迭代会依次对列表中的元素调用 Start Element.
- *** Test Cases ***
- Example
- :FOR ${element} IN @{ELEMENTS}
- \ Start Element ${element}
FOR循环的嵌套
Robot Framework的for语法并不支持嵌套, 不过可以通过用户关键字封装for循环, 然后在另一个for循环中调用.
- *** Keywords ***
- Handle Table
- [Arguments] @{table}
- :FOR ${row} IN @{table}
- \ Handle Row @{row}
- Handle Row
- [Arguments] @{row}
- :FOR ${cell} IN @{row}
- \ Handle Cell ${cell}
使用多个循环变量
和Python的for语句类似, 循环变量可以有多个. 该语法和正常的循环语句一样, 只是在 :FOR
和 IN
之间有多个循环变量, 每个变量占一格. 循环变量的个数可以是任意个, 但是它们必须能够被值的个数整除.
如果有很多值需要迭代, 通常会把它们在循环变量的下面组织对齐, 以提高可读性, 如下面例子中第一个循环:
- *** Test Cases ***
- Three loop variables
- :FOR ${index} ${english} ${finnish} IN
- ... 1 cat kissa
- ... 2 dog koira
- ... 3 horse hevonen
- \ Add to dictionary ${english} ${finnish} ${index}
- :FOR ${name} ${id} IN @{EMPLOYERS}
- \ Create ${name} ${id}
for-in-range 循环
前面的for循环总是迭代一个序列, 这是最常见的形式, 但是有时候, 针对某个特定次数的for循环也很有用. Robot Framework提高了特殊的 FOR index IN RANGE limit
语法来实现这种目的. 同样, 该语法借鉴于Python.
和普通的for循环类似, for-in-range循环同样始于 :FOR
, 后面跟循环变量. 只是这种情况下, 循环变量只能有一个, 该变量将包含当前循环的下标(index). 循环变量后的格子中必须包含 IN RANGE
, 后面的格子包含的是循环的限定范围.
最简单的情况是只给出循环的上限, 这种情况下, 循环下标从0开始, 逐次递加1, 直到上限为止(不包括上限). 还可以同时给出起始值(start)和结束值(end), 这种情况下, 循环从start开始, 逐次递加1, 直到end-1. 再复杂一点的情况是通过第3个参数指定每次递进的值(step), 该值可以为负数.
对上下限值可以使用简单的算术操作, 如加法和减法, 这在这些值是变量的时候特别有用.
从Robot Framework 2.8.7版本开始, start, end 和 step 都可以使用浮点数.
- *** Test Cases ***
- Only upper limit
- [Documentation] Loops over values from 0 to 9
- :FOR ${index} IN RANGE 10
- \ Log ${index}
- Start and end
- [Documentation] Loops over values from 1 to 10
- :FOR ${index} IN RANGE 1 11
- \ Log ${index}
- Also step given
- [Documentation] Loops over values 5, 15, and 25
- :FOR ${index} IN RANGE 5 26 10
- \ Log ${index}
- Negative step
- [Documentation] Loops over values 13, 3, and -7
- :FOR ${index} IN RANGE 13 -13 -10
- \ Log ${index}
- Arithmetics
- [Documentation] Arithmetics with variable
- :FOR ${index} IN RANGE ${var}+1
- \ Log ${index}
- Float parameters
- [Documentation] Loops over values 3.14, 4.34, and 5.34
- :FOR ${index} IN RANGE 3.14 6.09 1.2
- \ Log ${index}
for-in-enumerate 循环
有时候循环迭代某个列表的时候, 同时又想跟踪当前元素在列表中的位置, 这时候就可以用到Robot Framework的 FOR index … IN ENUMERATE …
语法. 该语法源于 Python built-in function.
For-in-enumerate循环和普通for循环一样, 只是在循环变量的前面增加一个额外的索引变量, 循环变量后面跟着的是 IN ENUMERATE
而不是 IN
. 索引值从0
开始.
例如, 下面例子中两个测试用例做得是同一件事:
- *** Variables ***
- @{LIST} a b c
- *** Test Cases ***
- Manage index manually
- ${index} = Set Variable -1
- : FOR ${item} IN @{LIST}
- \ ${index} = Evaluate ${index} + 1
- \ My Keyword ${index} ${item}
- For-in-enumerate
- : FOR ${index} ${item} IN ENUMERATE @{LIST}
- \ My Keyword ${index} ${item}
和普通的for循环一样, 一次迭代可以处理多个值, 只要列表元素的总数可以整除一次迭代的变量个数(当然索引变量是不算在内的).
- *** Test Case ***
- For-in-enumerate with two values per iteration
- :FOR ${index} ${english} ${finnish} IN ENUMERATE
- ... cat kissa
- ... dog koira
- ... horse hevonen
- \ Add to dictionary ${english} ${finnish} ${index}
For-in-enumerate 循环是 Robot Framework 2.9版本新增功能.
for-in-zip循环
有时候需要将几个相关的列表并在一起处理, Robot Framework 使用 FOR … IN ZIP …
语法来处理, 该方法来源于 Python built-in zip function.
来看个例子, 下面两个用例的作用是一样的:
- *** Variables ***
- @{NUMBERS} ${1} ${2} ${5}
- @{NAMES} one two five
- *** Test Cases ***
- Iterate over two lists manually
- ${length}= Get Length ${NUMBERS}
- : FOR ${idx} IN RANGE ${length}
- \ Number Should Be Named ${NUMBERS}[${idx}] ${NAMES}[${idx}]
- For-in-zip
- : FOR ${number} ${name} IN ZIP ${NUMBERS} ${NAMES}
- \ Number Should Be Named ${number} ${name}
和其它循环的语法类似, for-in-zip要求跟在循环变量后面格子中的是 IN ZIP
.
for-in-zip循环的值必须是列表或数组类型的序列, 并且循环变量的数量必须和列表的数量相同. 而迭代的停止取决于其中最短的那个列表.
注意, for-in-zip后面用到的列表通常都是以 标量变量 的形式给出, 如 ${list}
. 如果是 列表变量 形式, 则要求这个列表中的元素本身也是列表. (这里需要对着两种变量的格式理解充分)
For-in-zip 循环是 Robot Framework 2.9版本新增功能.
退出for循环
通常for循环在所有元素都迭代完成后自然结束, 也有可能当其中的关键字执行失败而退出. 如果需要提前退出循环, 可以调用 BuiltIn_ 关键字 Exit For Loop 和 Exit For Loop If. 它们的作用类似于编程语言中的 break
语句.
Exit For Loop 和 Exit For Loop If 可以直接在for循环内使用, 也可以在for循环中调用的关键字中使用. 这两种情况都可以让测试跳过循环继续往下执行. 不可以在for循环的外面使用了这两个关键字, 否则会引起错误.
- *** Test Cases ***
- Exit Example
- ${text} = Set Variable ${EMPTY}
- :FOR ${var} IN one two
- \ Run Keyword If '${var}' == 'two' Exit For Loop
- \ ${text} = Set Variable ${text}${var}
- Should Be Equal ${text} one
上例中, 可以使用 Exit For Loop If 来替代 Exit For Loop 加 Run Keyword If 的用法. 更多的信息和示例请参阅这些关键字的文档.
注解
Exit For Loop If 在Robot Framework 2.8版本新增.
继续for循环
除了退出整个for循环, 有时候需要的是略过本次迭代而进入下一轮迭代. 这时可以使用 BuiltIn_ 关键字 Continue For Loop 和 Continue For Loop If, 和编程语言中的 continue 语句类似.
Continue For Loop 和 Continue For Loop If 可以直接在for循环内使用, 也可以在for循环中调用的关键字中使用. 两种情况下都可以使得本次迭代被跳过, 进入下一次迭代. 如果本次迭代就是最后一次, 则整个循环结束. 同样, 在循环外调用这些关键字是错误的.
- *** Test Cases ***
- Continue Example
- ${text} = Set Variable ${EMPTY}
- :FOR ${var} IN one two three
- \ Continue For Loop If '${var}' == 'two'
- \ ${text} = Set Variable ${text}${var}
- Should Be Equal ${text} onethree
关于这些关键字更多的信息和示例请参阅它们在 BuiltIn_ 库的文档
注解
Continue For Loop 和 Continue For Loop If都是在Robot Framework 2.8版本新增.
去除输出中不必要的关键字
拥有多次迭代的for循环可以产生大量的输出信息, 从而造成 output_ 和 log_ 文件大小的显著增加. 从Robot Framework 2.7版本开始, 可以使用命令行选项 —RemoveKeywords FOR
从输出中 remove unnecessary keywords
__.
重复执行单个关键字
当每次循环只需要重复调用一个关键字的时候, 使用for循环显得有点小题大做. 这时候可以使用 BuiltIn_ 关键字 Repeat Keyword. 该关键字的第一个参数要重复的次数, 后面是要重复的关键字, 以及它的参数. 重复次数的值可以加上后缀 times
或者 x
以提高可读性.
- *** Test Cases ***
- Example
- Repeat Keyword 5 Some Keyword arg1 arg2
- Repeat Keyword 42 times My Keyword
- Repeat Keyword ${var} Another Keyword argument