关键字名称中嵌入参数

Robot Framework 除了常规的在关键字名称后指定参数的方法外, 还支持一种把参数嵌入到关键字名称中的做法. 这样做的最大好处是可以使得关键字如同正常语言中的句子一样易读.

基础语法

平常我们可以创建用户关键字如 Select dog from listSelects cat from list, 不过这些关键字需要各自独立创建. 而在关键字名称中嵌入参数的想法是只需要实现一个关键字 Select ${animal} from list.

  1. *** Keywords ***
  2. Select ${animal} from list
  3. Open Page Pet Selection
  4. Select Item From List animal_list ${animal}

嵌入参数的关键字不可接受”普通的”参数(即 [Arguments] 设置), 其它创建方式则没什么两样.

当关键字被调用时, 其名称中的不同的值自然地传递给对应位置的参数. 例如, 上例中的 ${animal} 在使用 Select dog from list 时的值就是 dog.

显然, 在关键字的内部这些参数不一定全部都得用上, 因此可以使用通配符.

这种类型的关键字和其它关键字的用法一样, 只是名称中的空格和下划线不能再忽略了. 不过大小写仍然是忽略的. 例如, 上例中的关键字可以是 select x from list, 但是不能是 Select x fromlist.

嵌入式参数不支持使用默认值和任意数量参数. 在调用这类关键字时也可以使用变量, 不过这样做会降低可读性.

另外请注意嵌入参数只适用于用户关键字.

嵌入参数过多匹配

使用嵌入参数的一个关键在于确保传入的值正确地匹配到参数. 特别在有多个参数, 并且参数值里面还有分隔字符存在时. 例如, 关键字 Select ${city} ${team} 在城市名中包含多个部分时就会错误, 如 Select Los Angeles Lakers.

一个简单的解决方法是把参数用引号括起来(例如 Select “${city}” “${team}”), 然后调用时同样使用引号传参(例如 Select “Los Angeles” “Lakers”).

强烈建议使用这种方式来调用, 尽管不能解决所有冲突, 但是它把参数和其它关键字区分了出来.

另一个更强大同时也更复杂的解决方案是使用 使用自定义正则表达式 来定义变量, 下节详细讨论.

此外, 如果这一切让事情变得非常复杂, 那么也许最好的方法是用回普通的位置型参数.

参数匹配过多的问题经常发生在为行为驱动用例创建 忽略前缀 的关键字的时候. 例如, ${name} goes home 匹配 Given Janne goes home 得到值为 Given Janne. 使用引号可以轻松的解决这个问题, 例如 “${name}” goes home.

使用自定义正则表达式

当调用嵌入参数的关键字时, 参数值在内部使用 正则表达式 (简称 regexps)来进行匹配. 默认的逻辑是每个参数用 .*? 模式替代, 该模式基本上可以匹配任何字符串. 正常情况下, 这样就足以胜任. 不过, 如前面讨论的一样, 有时候关键字会 匹配过多. 使用引号或其它分隔符有所帮助, 不过有时候情况比较复杂, 如下面的例子, 测试用例会执行失败, 因为关键字 I execute “ls” with “-lh” 同时匹配两个已定义的关键字.

  1. *** Test Cases ***
  2. Example
  3. I execute "ls"
  4. I execute "ls" with "-lh"
  5.  
  6. *** Keywords ***
  7. I execute "${cmd}"
  8. Run Process ${cmd} shell=True
  9.  
  10. I execute "${cmd}" with "${opts}"
  11. Run Process ${cmd} ${opts} shell=True

此时就可以使用自定义正则表达式来确保关键字只匹配到想要的确定的内容. 想要使用这个特性, 并且完全理解本节的例子, 你至少需要对正则表达式的基础语法有所了解.

自定义正则表达式的定义跟在参数的名称后面, 两者之间使用一个冒号(:)隔开. 例如, 一个只应该匹配数字的参数应该定义为 ${arg:\d+}. 请看下面的例子:

  1. *** Test Cases ***
  2. Example
  3. I execute "ls"
  4. I execute "ls" with "-lh"
  5. I type 1 + 2
  6. I type 53 - 11
  7. Today is 2011-06-27
  8.  
  9. *** Keywords ***
  10. I execute "${cmd:[^"]+}"
  11. Run Process ${cmd} shell=True
  12.  
  13. I execute "${cmd}" with "${opts}"
  14. Run Process ${cmd} ${opts} shell=True
  15.  
  16. I type ${a:\d+} ${operator:[+-]} ${b:\d+}
  17. Calculate ${a} ${operator} ${b}
  18.  
  19. Today is ${date:\d{4\}-\d{2\}-\d{2\}}
  20. Log ${date}

上例中, 关键字 I execute “ls” with “-lh” 仅匹配 I execute “${cmd}” with “${opts}”. 这是由 I execute “${cmd:[^”]}” 其中的正则表达式 [^"]+ 所保证的, 这个正则表达式意思是该参数不能包含任何引号. 在这个例子中, 对另外那个关键字 I execute 来说, 已经不必要再添加正则表达式.

小技巧

如果使用了引号, 使用正则表达式 [^"]+ 以确保参数的右引号匹配正确.

支持的正则表达式语法

因为Robot Framework是使用Python开发的, 所以其正则表达式语法很自然地是使用 re 模块中定义的 语法. 除了不能使用 (?…) 格式, 其它语法都可被支持.

注意嵌入参数的匹配是忽略大小写的. 如果正则表达式的语法非法, 则该关键字会创建失败, 并且在 测试执行错误区 中显示错误.

转义特殊字符

当使用嵌入参数regexp时, 某些特殊字符需要被转义才能使用.

首先, 正则模式中的右花括号 (}) 需要使用反斜杠转义(}), 否则该参数会提前结束. 例如, 在上面例子中的关键字 Today is ${date:\d{4}-\d{2}-\d{2}}.

反斜杠 (\) 作为Python正则表达式语法中的特殊字符, 如果你想要表示字面的反斜杠字符, 也需要进行转义. 这种情况最安全的做法是使用4个反斜杠序列(\\), 不过根据其后字符的不同, 有的情况两个反斜杠也已经足够.

注意, 按照正常的 测试数据转义规则, 关键字的名称和可能嵌入其中的参数名 不需要 被转义. 这意味着表达式 ${name:\w+} 中的反斜杠就不需要被转义.

在嵌入参数正则表达式中使用变量

不论何时使用到嵌入参数regexp, Robot Framework自动增强该正则表达式, 使得变量可以被匹配到. 这意味着总是可以在嵌入参数regexp的关键字中使用变量.

例如, 下面的用例使用到前面例子中的关键字, 测试结果为通过.

  1. *** Variables ***
  2. ${DATE} 2011-06-27
  3.  
  4. *** Test Cases ***
  5. Example
  6. I type ${1} + ${2}
  7. Today is ${DATE}

自动匹配变量的一个缺陷是变量的值有可能实际上并不真正匹配该特定的正则表达式. 例如, 上例中的 ${DATE} 可以包含任意值, 与此同时, Today is ${DATE} 将仍将会匹配到相同的关键字

行为驱动开发示例

把参数嵌入到关键字名称中最大的好处是可以使高层关键字更像是一句话, 从而写出 行为驱动样式 的测试用例. 详见下面的例子. 注意, 其中的前缀 Given, WhenThen并不是关键字名称的一部分.

  1. *** Test Cases ***
  2. Add two numbers
  3. Given I have Calculator open
  4. When I add 2 and 40
  5. Then result should be 42
  6.  
  7. Add negative numbers
  8. Given I have Calculator open
  9. When I add 1 and -2
  10. Then result should be -1
  11.  
  12. *** Keywords ***
  13. I have ${program} open
  14. Start Program ${program}
  15.  
  16. I add ${number 1} and ${number 2}
  17. Input Number ${number 1}
  18. Push Button +
  19. Input Number ${number 2}
  20. Push Button =
  21.  
  22. Result should be ${expected}
  23. ${result} = Get Result
  24. Should Be Equal ${result} ${expected}

注解

Embedded arguments feature in Robot Framework is inspired byhow step definitions are created in a popular BDD tool Cucumber.