RobotFramework 之 Python扩展关键字
Python函数作为关键字
前面简要了解了RF中可导入py文件中的内容,将python文件中的函数作为关键字使用,也就是自定义关键字
test.py
def ReturnList(n):
return [i for i in range(int(n))]
通过 Library test.py
导入py文件,将函数ReturnList
作为关键字使用
test1.robot
*** Settings ***
Library test.py
*** Test Cases ***
case1
${res} ReturnList 5
log to console ${res}
变量${res}
接收的内容为[0, 1, 2, 3, 4]
Python类作为测试库
使用Python类里的函数
新建一个py文件,testlib.py
,在该文件中定义一个类及相应的方法
testlib.py
class TestLibrary:
def _Return_List(self,n):
return [i for i in range(int(n))]
def Return_List(self,n):
return [i*i for i in range(int(n))]
通过在robot文件的Settings
中声明,即可调用Python类里的方法作为关键字使用
test2.robot
*** Settings ***
Library testlib.TestLibrary
*** Test Cases ***
case1
${res} Return List 5
log to console ${res}
通过命令robot -P . test2.robot
执行该robot文件(加上 -P
是为了将文件所在目录添加到PythonPath下,否则执行可能会报错,找不到TestLibrary
这个类)
执行该robot文件,日志打印的内容为 [0, 1, 4, 9, 16]
前面了解到,在robot文件中,会默认将python文件中函数名带-
的内容换成空格,而testlib.py
文件中定义了两个函数Return_List
和_Return_List
,robot文件中 Return List
执行的很明显是Return_List
显然这不是和函数的先后顺序有关,而是 Python类作为测试库时,RF在调用Python类中的成员方法,名称前带有-
前缀的函数不会作为关键字使用
Python扩展库的搜索规则
声明
规则一:如果类与模块同名,声明的时候可以省略后面的类名
把py文件的名称改为 TestLibrary.py
,robot文件中在 Settings
表中改为 Library TestLibrary
test1.robot
*** Settings ***
Library config.TestLibrary
*** Test Cases ***
case1
${res} Return List 5
log to console ${res}
执行robot文件,可以发现case1
依旧正常运行,调用了 Return List
关键字
注意: 这种方式并不推荐使用,命名最好还是不要相同,命名最好规范,不要有重名的函数,大小写也要进行区分,这样可以规避掉一些不必要的麻烦。指不定哪个版本开始就不兼容了,或者出现一些其他的问题,项目维护起来就很麻烦了
导包
规则二:导包规则
导包以项目根目录为准
此时,testlib.py
文件在 config
包下, config
包与 test1.robot
文件同级(属于项目根目录下的一级目录与文件)。
testlib.py
def Return_num(n):
return n
class TestLibrary:
def Return_List(self,n):
return [i*i for i in range(int(n))]
在robot文件的Settings
中声明,有两种方式:
- 模块法:点
.
作为分隔符 - 路径法:斜杠
/
作为分隔符
在Settings
表中声明用python类做的测试库
,用模块法
test1.robot
*** Settings ***
Library config.testlib.TestLibrary
*** Test Cases ***
case1
${res} Return List 5
log to console ${res}
这里是使用了testlib.py
文件里TestLibrary
类中的Return_List
函数,TestLibrary
类作为了测试库,关键字Return List
是使用测试库里的内容使用,所以模块法的内容需要到TestLibrary
在Settings
表中声明资源文件和变量文件
,用路径法或模块法
test2.robot
*** Settings ***
Library config/testlib.py
Library config.testlib
*** Test Cases ***
case1
${res} Return_num 5
log to console ${res}
这里是使用了testlib.py
文件里的Return_num
函数,testlib.py
作为了资源文件
使用
模块法的内容只需要到testlib.py
文件即可
而使用路径法,需要识别到这个testlib.py
文件,所以需要加上.py
后缀
注意: 如果一个py文件中已经创建了一个类,然后要在 robot文件中使用该py文件中类中的函数作为关键字,那么在这个py文件中,除了类里的函数,不推荐再从类外面创建函数,这样可以规避掉一些在 robot文件中使用关键字报错的问题。可以新建一个py文件,在里面新建函数。
Python库中的class
类的初始化
通常情况下,项目迭代会有多个测试环境,不同测试环境下有不同的ip和端口号,通过Python自定义关键字的方式,实现记录不同测试环境下的ip和端口号这一日志功能
testlib.py
文件里定义了一个TestLibrary
类,初始化类的时候,需要传入ip和端口号两个参数,通过LoginInfo
函数实现返回记录地址及时间
testlib.py
import time
from robot.api import logger
class TestLibrary:
def __init__(self,host,port):
logger.console('执行初始化')
self.host=host
self.port=port
dt = time.localtime()
logintime = time.strftime('%Y-%m-%d %H:%M:%S', dt)
self.logintime = logintime
def LoginInfo(self):
WebInfo = 'http://' + self.host +':'+ self.port +'--' + self.logintime
return WebInfo
在robot文件中,由于初始化类的时候,需要传入ip和端口号两个参数,所以在声明 TestLibrary
类 时,通过Library testlib.TestLibrary 127.0.0.1 8080
传入这两个参数
test.robot
*** Settings ***
Library config.testlib.TestLibrary 127.0.0.1 8080
*** Keywords ***
记录访问日志
${info} LoginInfo
log to console ${info}
*** Test Cases ***
case1
记录访问日志
通过命令 robot -P . test.robot
,robot文件执行成功
==============================================================================
case1 执行初始化
http://127.0.0.1:8080--2021-04-10 20:03:20
case1 | PASS |
------------------------------------------------------------------------------
Test1 | PASS |
1 test, 1 passed, 0 failed
==============================================================================
类的继承
遇到继承问题,导入库只需导入子类即可
新建一个base.py
文件,里面创建一个Father
类
base.py
from robot.api import logger
class Father():
def __init__(self):
logger.console('执行父类方法')
def GiveMoney(self):
self.money = 10000
logger.console('父亲一次给10000元')
def ShowMoney(self):
logger.console(self.money)
logger.console('父亲给的钱的余额')
return self.money
一个other.py
文件,里面创建一个Child
类,Child
类继承Father
类
other.py
from config.base import Father
from robot.api import logger
class Child(Father):
def UseMoney(self):
self.money -= 2000
logger.console('熊孩子一次花2000')
在robot文件中使用other.py
文件里的Child
类作为测试库,执行该robot文件
test.robot
*** Settings ***
Library config.other.Child
*** Test Cases ***
case1
UseMoney
ShowMoney
执行会报错:AttributeError: 'Child' object has no attribute 'money'
。报错的意思是Child
类没有money
这个属性。因为“没有向父亲拿钱,所以没有钱”。这时候要先调用一下GiveMoney
test.robot
*** Settings ***
Library config.other.Child
*** Test Cases ***
case1
GiveMoney
UseMoney
ShowMoney
执行
==============================================================================
case1 执行父类方法
父亲一次给10000元
.熊孩子一次花2000
父亲给的钱的余额
8000
case1 | PASS |
------------------------------------------------------------------------------
Test1 | PASS |
1 test, 1 passed, 0 failed
当然,有时候父亲可能比较开心,比如打牌打赢了,多给了一些钱,又或者熊孩子花钱花多次,且大手大脚,这个money
,在robot文件中也可以作为参数进行传递
base.py
from robot.api import logger
class Father():
def __init__(self):
logger.console('执行父类方法')
def GiveMoney(self,give=10000):
self.money = give
logger.console('父亲一次给{}元'.format(give))
def ShowMoney(self):
logger.console('父亲给的钱的余额')
logger.console(self.money)
return self.money
other.py
from config.base import Father
from robot.api import logger
class Child(Father):
def UseMoney(self,cost=2000):
self.money -= cost
logger.console('熊孩子一次花{}'.format(cost))
test.robot
*** Settings ***
Library config.other.Child
*** Test Cases ***
case1
GiveMoney 30000
UseMoney 1000
UseMoney 2000
UseMoney 3000
${res} ShowMoney
执行robot文件
==============================================================================
Test1
==============================================================================
case1 执行父类方法
父亲一次给30000元
.熊孩子一次花1000
.熊孩子一次花2000
.熊孩子一次花3000
.父亲给的钱的余额
24000
case1 | PASS |
------------------------------------------------------------------------------