FOR循环

在自动化测试中, 将某些操作重复执行若干次是一个很常见的需求. 在Robot Framework中, 测试库中可以有任意形式的循环结构, 大多数时候循环操作本应该就在测试库中实现.

Robot Framework也提供了for循环的语法, 这在重复执行来自不同测试库中的关键字的时候很有用.

for循环既可用于测试用例, 也可以在用户关键字中使用. 除非场景特别简单, 不然还是推荐在用户关键字中使用, 这样可以隐藏for循环带来的复杂度. 基本的for循环语法 FOR item IN sequence 借鉴于Python, 不过其它脚本如Perl也有类似的语法.

普通FOR循环

普通的for循环语法中, 每次迭代都从列表中取一个值赋给变量. 语法以 :FOR 开始, 注意开始的冒号是必需的, 以便和其它普通关键字区分开. 跟在后面单元格中的是循环变量, 接下来的格子则必须是 IN, 后面的格子(可能是多个)里则包含的是待迭代的值. 这些值中可以包含 变量, 包括 列表变量.

for循环中使用的关键字跟在下面的行中, 必须向右缩进一格. 当使用的是 纯文本格式, 缩进单元格必须使用 反斜杠转义, 而其它的数据格式则只需要保持空白就行. for循环结束于正常缩进(即不再缩进)的行, 或者是整个表格的结尾.

  1. *** Test Cases ***
  2. Example 1
  3. :FOR ${animal} IN cat dog
  4. \ Log ${animal}
  5. \ Log 2nd keyword
  6. Log Outside loop
  7.  
  8. Example 2
  9. :FOR ${var} IN one two
  10. ... ${3} four ${last}
  11. \ Log ${var}

上面 Example 1 将迭代执行两次, 第一次循环变量 ${animal} 被赋值 cat, 接下来是 dog. 循环体包含了两次 Log 关键字调用. 第二个例子中, 循环值 分成了多行, 循环迭代了5次.

在for循环中使用 列表变量 更方便. 如下面的例子, @{ELEMENTS} 是任意长度的列表, 每次迭代会依次对列表中的元素调用 Start Element.

  1. *** Test Cases ***
  2. Example
  3. :FOR ${element} IN @{ELEMENTS}
  4. \ Start Element ${element}

FOR循环的嵌套

Robot Framework的for语法并不支持嵌套, 不过可以通过用户关键字封装for循环, 然后在另一个for循环中调用.

  1. *** Keywords ***
  2. Handle Table
  3. [Arguments] @{table}
  4. :FOR ${row} IN @{table}
  5. \ Handle Row @{row}
  6.  
  7. Handle Row
  8. [Arguments] @{row}
  9. :FOR ${cell} IN @{row}
  10. \ Handle Cell ${cell}

使用多个循环变量

和Python的for语句类似, 循环变量可以有多个. 该语法和正常的循环语句一样, 只是在 :FORIN 之间有多个循环变量, 每个变量占一格. 循环变量的个数可以是任意个, 但是它们必须能够被值的个数整除.

如果有很多值需要迭代, 通常会把它们在循环变量的下面组织对齐, 以提高可读性, 如下面例子中第一个循环:

  1. *** Test Cases ***
  2. Three loop variables
  3. :FOR ${index} ${english} ${finnish} IN
  4. ... 1 cat kissa
  5. ... 2 dog koira
  6. ... 3 horse hevonen
  7. \ Add to dictionary ${english} ${finnish} ${index}
  8. :FOR ${name} ${id} IN @{EMPLOYERS}
  9. \ 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 都可以使用浮点数.

  1. *** Test Cases ***
  2. Only upper limit
  3. [Documentation] Loops over values from 0 to 9
  4. :FOR ${index} IN RANGE 10
  5. \ Log ${index}
  6.  
  7. Start and end
  8. [Documentation] Loops over values from 1 to 10
  9. :FOR ${index} IN RANGE 1 11
  10. \ Log ${index}
  11.  
  12. Also step given
  13. [Documentation] Loops over values 5, 15, and 25
  14. :FOR ${index} IN RANGE 5 26 10
  15. \ Log ${index}
  16.  
  17. Negative step
  18. [Documentation] Loops over values 13, 3, and -7
  19. :FOR ${index} IN RANGE 13 -13 -10
  20. \ Log ${index}
  21.  
  22. Arithmetics
  23. [Documentation] Arithmetics with variable
  24. :FOR ${index} IN RANGE ${var}+1
  25. \ Log ${index}
  26.  
  27. Float parameters
  28. [Documentation] Loops over values 3.14, 4.34, and 5.34
  29. :FOR ${index} IN RANGE 3.14 6.09 1.2
  30. \ Log ${index}

for-in-enumerate 循环

有时候循环迭代某个列表的时候, 同时又想跟踪当前元素在列表中的位置, 这时候就可以用到Robot Framework的 FOR index … IN ENUMERATE … 语法. 该语法源于 Python built-in function.

For-in-enumerate循环和普通for循环一样, 只是在循环变量的前面增加一个额外的索引变量, 循环变量后面跟着的是 IN ENUMERATE 而不是 IN. 索引值从0开始.

例如, 下面例子中两个测试用例做得是同一件事:

  1. *** Variables ***
  2. @{LIST} a b c
  3.  
  4. *** Test Cases ***
  5. Manage index manually
  6. ${index} = Set Variable -1
  7. : FOR ${item} IN @{LIST}
  8. \ ${index} = Evaluate ${index} + 1
  9. \ My Keyword ${index} ${item}
  10.  
  11. For-in-enumerate
  12. : FOR ${index} ${item} IN ENUMERATE @{LIST}
  13. \ My Keyword ${index} ${item}

和普通的for循环一样, 一次迭代可以处理多个值, 只要列表元素的总数可以整除一次迭代的变量个数(当然索引变量是不算在内的).

  1. *** Test Case ***
  2. For-in-enumerate with two values per iteration
  3. :FOR ${index} ${english} ${finnish} IN ENUMERATE
  4. ... cat kissa
  5. ... dog koira
  6. ... horse hevonen
  7. \ 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.

来看个例子, 下面两个用例的作用是一样的:

  1. *** Variables ***
  2. @{NUMBERS} ${1} ${2} ${5}
  3. @{NAMES} one two five
  4.  
  5. *** Test Cases ***
  6. Iterate over two lists manually
  7. ${length}= Get Length ${NUMBERS}
  8. : FOR ${idx} IN RANGE ${length}
  9. \ Number Should Be Named ${NUMBERS}[${idx}] ${NAMES}[${idx}]
  10.  
  11. For-in-zip
  12. : FOR ${number} ${name} IN ZIP ${NUMBERS} ${NAMES}
  13. \ 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 LoopExit For Loop If. 它们的作用类似于编程语言中的 break 语句.

Exit For LoopExit For Loop If 可以直接在for循环内使用, 也可以在for循环中调用的关键字中使用. 这两种情况都可以让测试跳过循环继续往下执行. 不可以在for循环的外面使用了这两个关键字, 否则会引起错误.

  1. *** Test Cases ***
  2. Exit Example
  3. ${text} = Set Variable ${EMPTY}
  4. :FOR ${var} IN one two
  5. \ Run Keyword If '${var}' == 'two' Exit For Loop
  6. \ ${text} = Set Variable ${text}${var}
  7. Should Be Equal ${text} one

上例中, 可以使用 Exit For Loop If 来替代 Exit For LoopRun Keyword If 的用法. 更多的信息和示例请参阅这些关键字的文档.

注解

Exit For Loop If 在Robot Framework 2.8版本新增.

继续for循环

除了退出整个for循环, 有时候需要的是略过本次迭代而进入下一轮迭代. 这时可以使用 BuiltIn_ 关键字 Continue For LoopContinue For Loop If, 和编程语言中的 continue 语句类似.

Continue For LoopContinue For Loop If 可以直接在for循环内使用, 也可以在for循环中调用的关键字中使用. 两种情况下都可以使得本次迭代被跳过, 进入下一次迭代. 如果本次迭代就是最后一次, 则整个循环结束. 同样, 在循环外调用这些关键字是错误的.

  1. *** Test Cases ***
  2. Continue Example
  3. ${text} = Set Variable ${EMPTY}
  4. :FOR ${var} IN one two three
  5. \ Continue For Loop If '${var}' == 'two'
  6. \ ${text} = Set Variable ${text}${var}
  7. Should Be Equal ${text} onethree

关于这些关键字更多的信息和示例请参阅它们在 BuiltIn_ 库的文档

注解

Continue For LoopContinue 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 以提高可读性.

  1. *** Test Cases ***
  2. Example
  3. Repeat Keyword 5 Some Keyword arg1 arg2
  4. Repeat Keyword 42 times My Keyword
  5. Repeat Keyword ${var} Another Keyword argument