Run Keyword If
RF 里面除了循环以外,另一个流程控制的基本功能就是条件判断,RF 中通常用 Run Keyword If 关键字来达到类似 Python 中 if…else… 条件判断的功能,我们打开官方文档看一下:
http://robotframework.org/robotframework/latest/libraries/BuiltIn.html#Run%20Keyword%20If
第一列是关键字的名字,第二列是关键字的参数,他有三个参数 condition, name, *args
我们来看一下它的说明 Runs the given keyword with the given arguments, if condition is true.
如果 condition 为真的话,那么就执行
这里given keyword with...
就是 name 代表的 keyword with, *args
就是关键字的参数,就是 name 对应的参数,如果 condition 为 True 的话。
接下来看下 condition 是怎么定义的。
这句话它说 condition 是 python 的表达式(之前我们学的 should Be True 也是),name 是一个关键字 就是条件满足的时候要执行的关键字,并且只能执行一个关键字
我们来看个例子:
run keyword if '2017' in $html log to console 内容
判断 '2017' 如果在'$html'
这个变量里面,如果 '2017' 在这个字符串里面,如果是 True 的话为真,那么就执行 Log to console 就打印,内容就是 Log to console 所对应的参数。注意这里的condition'2017' in $html
是python的表达式,要注意 python表达式变量的写法,只加$
不用加 {}。
那现在我们涉及一个库函数,比如我有一个 url 我们要获取 url 里面的内容,我们来看一个例子:
这里我自己定义了一个库函数 getWebInfo , getWebInfo 里面取到了 url 的内容,内容是:
我们取到的就是时间的一个字符串,返回的是一个 text 就是刚才的字符串,我们马上用这个keyword 实现使用这个关键字获得网页的内容,看一个 robot 的例子
*** Settings ***
Library mylib4
*** Test Cases ***
测试1
${html}= getwebinfo
run keyword if '2018' in $html log to console \n2018年的,UTC时间
我们引入 mylib4.py 之后用 getwebinfo 取出它的值然后存到${html}
变量里,后面做了判断如果 2018 在$html
里面,那我们就 log to console 打印下 2018 年的 UTC 时间。
运行结果。
因为 '2018' in $html 是为 True 的,就打印 2018 年的 UTC 时间。
讲一个注意点:
这里路径不需要设置因为这里我们把 mylib4.py 和 s1.robot 放在同级目录下面的,同级目录下 robot 去找的路径跟 python 一样,先在当前执行的 s1.robot 路径下去找,如果找到了就用,如果找不到就去 site-packages 下面去找,这里因为是同级目录所以直接写没有什么问题,如果找不到就在前面加上 --pythonpath . 把它设置为你当前的路径,这种情况下找的话首先要 cd 到当前执行的路径下面。
如果不行的话要加上 --pythonpath .。
我们再考虑个问题如果条件判断再复杂一点如果有多个条件,比如说我除了包含2018还要包含UTC都满足我再打印log,这个时候该怎么写大家想一下,这个 condition 有两个判断条件,既然中间的 condition 是一个 python 表达式,那就很简单了加个 and 就行了。
*** Settings ***
Library mylib4.py
*** Test Cases ***
测试1
${html}= getwebinfo
run keyword if '2018' in $html and 'UTC' in $html
... log to console \n2018年的,UTC时间
这完全是我们 python 表达式的写法,这边有一个换行要注意下 RF中解决太长的问题,可以用下一行前面加 三个点 的省略号,在测试用例中,下一行的省略号前面必须留有一个以上的空单元格并且后面也要空两个以上的单元格。
注意这里有1个条件不满足执行结果也是 pass,比如我们把 UTC 改为 UTC1,运行结果也是 pass
*** Settings ***
Library mylib4.py
*** Test Cases ***
测试1
${html}= getwebinfo
run keyword if '2018' in $html and 'UTC1' in $html
... log to console \n2018年的,UTC时间
运行结果:
但是没有打印“2018年的UTC时间”,因为这个条件不满足,大家要注意这个 run keyword if 他不是一个检查点的关键字,所以这个条件不满足就不执行下面的语句,但是整个 Case 是不会 FAIL 的,它是一个 pass 的。
ELSE 分支
既然编程语言中有 if 那很自言的就会想到 ELSE 分支,在老版本的 Robot Framework 是没有 ELSE 分支的,它只有另外一个关键字 run keyword unless 关键字,这个关键字和我们 python 里面的 if else 是不一样的,因为 python 里面的 if else 是放在一起的,不可能只有 else 没有 if ,他必须先有 if 再有非 if 的 else 条件,那么 Robot Framework 早期的版本里面 run keyword unless 它和 run keyword if 它俩其实不是有关联的,它俩没有任何关联关系的两个关键字,就算前面没有 run keyword if 这个关键字,直接 run keyword unless 也是可以的。
他是可以独立存在的,不像 python 的 if else 是嵌套在一起的。大家要理解一下,它是一个全新的语句,正因为他们可以单独使用所以条件还要在写一遍。
。
大家看下 run keyword if 要加上条件,条件满足的满足的话执行下面的关键字 Log to console ,run keyword unless 就是不满足的时候才去执行 Log to console 所以他跟上面没有关联所以条件要再写一遍,因为可以独立存在单独执行是没有问题的,从这个语法上就看到了这两个 keyword 放在一起,这样实现 if else 的功能是不是有点复杂啰嗦,要把条件写两遍才能达到需求。所以 Robot Framework 从 2.7.4 以后他也支持 else 的分支了,他的语法写反就可以了,如果 unless 想改成 run keyword if 就是:
其实是一样的,语法写反完全可以达到需求的,只是 Robot 是相对弱的语法,所以它里面搞了很多看起来有点相近的关键字去实现不同的功能,大家理解一下。
在新的2.7.4以后的 robot 他就有了 ELSE 分支,因为他也发现用起来比较不舒服,写起来有点重复,所以它也支持了 ELSE 及 ELSE IF 这种分支,格式就是另外起一行前面加省略号就是换行的意思。
这个他们就是放在一起的作为 run keyword if 的一些参数放在里面这些 ELSE IF ,
这样写就不需要把条件再写一遍了,大家注意这里的 ELSE 本身就不是一个关键字他是run keyword if
这里面参数的一部分,所以第一他们前面要有省略号,第二ELSE IF
一定要全部大写的,例子:
*** Settings ***
Library mylib4
*** Test Cases ***
测试1
${html}= getwebinfo
run keyword if '2016' in $html and 'UTC' in $html
... log to console \n2016年的,UTC时间
... ELSE IF '2016' in $html log to console \n2016年的
... ELSE IF 'UTC' in $html log to console \nUTC时间
... ELSE log to console \n以上都不是
如果2016年和 UTC 都在$html
里面就打印2016年的,UTC时间,如果只2016在的话就打印 2016年的,如果只UT在的话就打印 UTC时间 ,最后的条件就是都不满足那就打印以上都不是,这就是他的语法跟 python 有些相像只是写法、换行、空格以及ELSE IF 的大写要注意一下,看运行结果:
上一次我们讲了循环,循环也有判断的逻辑在里面,现在我们做一个功能,弹出一个对话框让用户来输入自己的体重,然后对体重做一个判断比如太胖了,太瘦了等等,我们在做之前要想想要弹出对话框,让用户输入在 Robot Framework 里面用什么库去实现,这里给大家介绍一个 Dialogs 的库,大家来看一下,里面有个关键字叫 Get Value From User。
http://robotframework.org/robotframework/latest/libraries/Dialogs.html
从名字的含以上就可以看出从 User 这边取值,他有三个参数叫 mseeage、default_value、hidden,这边说Pauses test execution and asks user to input a value.
暂停测试执行等用户去输入数据,这个是不是就可以达到需求让用户去输入一个字符,这种一般用在半自动化的地方,他停在某个地方弹出一个对话框让用户去输入一个值,我们看一下怎么实现这个功能。
*** Settings ***
Library Dialogs
*** Test Cases ***
测试1
${weight}= get value from user 请输入你的体重 60
log to console 体重为${weight}
run keyword if int($weight)>60 log to console 太重了
解析一下代码,首先导入 Dialogs ,里面有个关键字叫 get value from user 他的第一个参数是 mseeage 就是对话框上弹出的值。
如果不输入会给一个 default 的参数,我们给一个 default 的值,我们这里就是弹出的对话框里写的是请输入你的体重默认是60,我们把 get value from user 返回值存到${weight}
里面,然后先打印一下体重是多少 log to console 体重为 ${weight}
,然后我们做了一个判断如果体重大于60我们就打印一下太重了 run keyword if int($weight)>60 log to console 太重了,我们这里先实现一个简单的不带循环的判断,然后在往里加循环,我们运行一下输入61运行结果:
我们执行会发现我们执行完之后窗口马上就关了,测试就关闭了,假如有三十个同学每个人都把自己的体重都测一下看看是轻了还是重了,每个人都输入一下反复提供输入框,这里就需要用循环了来实现了,python 里面的无限循环我们用的是 While,那我们就找一下 Robot Framework 里面有没有类似 while 的这种关键字,通过寻找 Robot Framework 并没有这样一个关键字,所以如果我们想在 Robot Framework 模拟一个类似while 的无限循环,我们就只能用一个大的 range 来模拟 while 并且用 Exit For Loop 退出循环来实现 python的 break 的功能,如果${weight}
等于 over 的话就退出循环,大家看下这段代码
*** Settings ***
Library Dialogs
*** Test Cases ***
测试1
:for ${one} in range 9999
\ ${weight}= get value from user 请输入你的体重 60
\ run keyword if $weight=='over' EXIT FOR LOOP
\ run keyword if int($weight)>60 log to console 太重了
\ ... ELSE log to console 太轻了
前面是两个冒号:加个 for ,有一个参数${one}
虽然这个参数没有用但是我们必须写一个在这,然后 in range 这里写的比较大,接下是${weight}= get value from user 请输入你的体重 60
先输入用户的体重,run keyword if $weight=='over' EXIT FOR LOOP
如果weight=='over'
就退出循环,\ run keyword if int($weight)>60 log to console 太重了
如果这个体重大于60就打印太重了,ELSE
就是太轻了。
注意 run keyword if 和 ELSE 是一起的,ELSE 是 run keyword if 里面的一个参数相当于所以必须加...,并且前面讲的 for 循环的缩进要注意一下,刚刚说的循环大家应该还会想到一个关键字 python 里面的 continue ,在 Robot Framework 有个关键字交Continue For Loop 实现 python 里面的continue 功能。
*** Settings ***
Library Dialogs
*** Test Cases ***
测试1
:for ${one} in range 9999
\ ${weight}= get value from user 请输入你的体重 60
\ run keyword if $weight=='cont' continue for loop
\ run keyword if $weight=='over' EXIT FOR LOOP
\ run keyword if int($weight)>60 log to console 太重了
\ ... ELSE log to console 太轻了
如果输入框输入 over 那么就 EXIT FOR LOOP 退出循环,如果输入cont 那么就continue for loop 其他逻辑跟以前一样。
在 Robot Framework 里面有等价的关键字会让他写起来更简单一点,比如 run keyword if 和 continue for loop ,run keyword if 和 EXIT FOR LOOP ,我们可以简略 exit for loop if 和 continue for loop if
我们现在替换一下
*** Settings ***
Library Dialogs
*** Test Cases ***
测试1
:for ${one} in range 9999
\ ${weight}= get value from user 请输入你的体重 60
\ continue for loop if $weight=='cont'
\ exit for loop if $weight=='over'
\ run keyword if int($weight)>60 log to console 太重了
\ ... ELSE log to console 太轻了
效果是一样的。
Robot 语法比较弱所以他对一些关键字的封装就比较多,实现一些简单的功能有好多关键字,如果有很复杂的循环、判断逻辑在里面一般还是建议大家用 python 去封装关键字去使用会更好一点。我们上次介绍的 should be true 和今天介绍的 run keyword if 他们的参数都是一个表达式,在 python 里面调用的是 Eval 来执行的,他的主要目的就是判断结果是不是为 True 的,用 Eval 做一个表达式的最后结果的判断,大家想一下我们为什么要用 Eval,我们看个例子下面有两行 python 代码。
exp = input('请输入表达式')
print(eval(exp))
input 一个表达式,直接 print eval 的 exp,我们执行一下输入4+5输出了一个9出来,这里我们用 eval 就是因为他能动态的把表达式当做 python 的代码去执行,如果不用 eval 的话,我输入的什么他输出的就是什么,不会帮我们做计算的,在我们 Robot 里面有没有像 eval 这样一个关键字?也是在python里面调用eval得到的结果,用它的结果去赋值呢,这样就等于我们可以在 robot 里面直接调用 python 的代码表达式来生成一个结果,这样灵活度就很高了,现在我们就介绍一个实现类似一个在 python 里面eval 的关键字,在robot 里面有一个关键字叫Evaluate 这个关键字。
以前定义变量我们用 set variable
${var}= set variable ${890}
用 evaluate 的写法
${var}= evaluate 890
我们再举个例子
*** Test Cases ***
测试1
${var1}= create list Hello word
${var2}= evaluate ['hello','world']
${var3}= evaluate ['hello']*10
log to console ${var1}
log to console ${var2}
log to console ${var3}
我们之前创建一个列表我们有一个 create list 的关键字,${var1}= create list Hello word
用create list 关键字创建一个列表赋值给${var1}
,我们完全用 evaluate 方式去写大家看一下${var2}= evaluate ['hello','world]
直接 Evaluate 后面跟 python list 的格式直接赋值给${var2}
,这样的好处是:直接用 Evaluate 不用记那么多关键字了,灵活度也比较高比如我想创建一个字符串包含10个 hello 直接这样写就可以。
${var3}= evaluate ['hello']*10
运行结果: