大家好,我是洋子,今天给大家分享一下Robot Framework自动化测试框架的使用教程,Robot Framework是一个可扩展
、关键字驱动
的测试自动化框架,可用于做接口、UI自动化,并且可以使用 Python 或者Java 去编写测试用例依赖的lib库,是一款非常强大的测试框架
看了网上大量文章,基本都是使用Robot Framework的RIDE来进行测试,RIDE即为Robot的图形化编辑界面,操作起来并不是很方便,所以本文将教大家直接使用Python
和Robot命令
来进行自动化测试,便于用例执行和扩展,大厂基本都在这样用,便于和CI(持续集成)流水线结合执行测试用例
在编写用例的基础之上,我还会教大家设计、搭建自动化测试框架,满足企业级的自动化测试需求
本期教程包括以下部分内容
Robot Framework是用Python实现的,也可以在Jython(JVM)和 IronPython(.NET)解释器上运行。在安装框架之前,一个明显的前提条件是安装所需的解释器
本文只介绍使用Python去安装Robot Framework框架以及使用Python去编写robot框架的自定义参数、lib库等,因为这是最主流也是最方便的使用方式
Python 2 在2020年已停止维护,所以建议大家都安装Python 3.x 版本
Unix & Linux 安装 Python
Windows 安装 Python
MAC 安装 Python
brew install python3
即可安装robotframework,最简单的方式是通过pip安装
pip install robotframework
python的requests库,用来发送HTTP请求,做接口自动化
测试需要使用到
pip install requests
在mac 命令行下使用pip命令 前面 还需要加sudo命令,否则会提示无权限
安装 selenium2library库,用来做Web UI自动化
测试(若只使用robot框架做接口自动化,此库可不安装)
pip install robotframework-selenium2library
到此为止,Robot Framework 框架以及所需要的依赖环境全部安装完毕
前言我们提到Robot Framework是关键字驱动
的测试自动化框架,这个关键字可以理解成Robot框架的语法,掌握了关键字的含义,我们才能更好的编写测试用例,在Robot框架中有两类关键字,一类是系统自带的关键字,另一类是自定义关键字。当系统关键字不满足我们的测试需求时,就可以基于Python自定义关键字,然后使用自定义的关键字去编写测试用例
为方便讲解,首先创建三个list变量:list_a、list_b、list_c;以及两个scalar变量(scalar变量就是一种标量变量,存放字符串或者数字):string和name。本节知识可先跳过,后面使用到做参考即可
@{list_a} create list 1 a ${21} 21 12
@{list_b} set variable 1.0 a ${21} 21 21
@{list_c} create list
${string} set variable pengliwen is in hangzhou
${name} set variable plw
备注:以下提供的用例都是断言成功
should contain ${list_b} 1.0
should not contain ${list_b} 1
should contain x times ${list_b} 21 2
说明:变量{list_b}包含对象1.0而不包含对象1,且对象21在变量{list_b}出现了两次。
should be empty ${list_c}
should not be empty ${list_a}
说明:变量{list_c}没有赋值,所以为空;相反,变量{list_a}有赋初始值,故为非空。
should be equal ${list_a[1]} ${list_b[1]}
should not be equal ${list_a} ${list_b}
说明:{list_a[1]}=a,{list_b[1]}=a故两个对象相等;而{list_a}和{list_b}有元素不一致,这两个对象不相等
Should Be Equal As Numbers ${list_b[0]} 1.0000
Should not Be Equal As Numbers ${list_b[0]} 1.1
说明:${list_b[0]}=1,忽略精度,故与1.0000相等;而即使是忽略精度,1与1.1还是不相等的;
Should Be Equal As Integers ${list_a[3]} ${list_b[3]}
Should not Be Equal As Integers ${list_a[4]} ${list_b[4]}
说明:{list_a[3]}=21,{list_b[3]}=21,而系统默认为字符串格式的“21”,故需要转化为整数类型,转化为整数后两个对象相等;{list_a[4]}=12,{list_b[4]}=21,即使转化为整数后两个对象依旧是不相等;
Should Be Equal As Strings ${list_a[2]} ${list_b[2]}
Should not Be Equal As Strings ${list_a[0]} ${list_b[0]}
说明:{list_a[2]}={21},{list_b[2]}={21},而均为数值型的21,故需要转化为字符串类型,转化为字符串后两个对象相等;
Should Be True ${list_a[0]} < 10
Should not Be True ${list_a[0]} < 1
说明:${list_a[0]}=1(字符串类型),其ASCII值比字符串10的ASCII值小;
Should start With ${string} peng
Should not start With ${string} h
说明:${string}=”pengliwen is in hangzhou“是以peng开头,而非以h开头;
Should End With ${string} hangzhou
Should not End With ${string} pengliwen
说明:${string}=”pengliwen is in hangzhou“是以hangzhou结尾,而非以pengliwen结尾;
should match ${name} p??
should not match ${string} h?*
说明:模式匹配和shell中的通配符类似,它区分大小写,'*'匹配0~无穷多个字符,“?”单个字符
${name}=plw,由以p开头的三个字母组成
Should Match Regexp ${name} ^\\w{3}$
Should not Match Regexp ${name} ^\\d{3}$
说明:反斜杠在测试数据是转义字符,因此模式中要使用双重转义;'^'和'$'字符可以用来表示字符串的开头和结尾
${name}=plw,是有三个字母--w{3}组成,而不是由三个数字--d{3}组成。
除了系统关键字,我们还可以编写Python文件自定义关键字,格式如下
import requests
from robot.api.deco import keyword
class HttpLibrary(object):
""" Http Request Library """
def __init__(self):
""" 初始化 session """
self.session = {}
@keyword('Create Http')
def create(self, alias, url, headers=None, cookies=None, timeout=None):
""" 创建一个 Http 连接代理 """
pass
@keyword('Post Http')
def post(self, alias, path='', data='{}', isJsonStr=False):
""" 执行 POST 请求 """
pass
@keyword('Get Http')
def get(self, alias, path='', data='{}', is_log=True):
""" 执行 GET 请求 """
pass
@keyword('Json Post Http')
def jsonpost(self, alias, path='', data='{}'):
""" 执行 POST 请求(body为json格式) """
pass
上面的Python文件定义了一个类,可以看到该文件当中除了init构造方法,其他每个方法都由keyword装饰器修饰,分别定义了Create Http
、Post Http
、Get Http
、Json Post Http
这4个自定义关键字,如果还需要其他自定义关键字,按照这个结构继续添加就行
至于自定义关键字和系统自带的关键字如何使用,在下面 创建测试用例 章节会讲到
现在虽然安装好了robotframework的运行环境,也能直接开始编写测试用例,但我们还要想到一个问题,如果用例数量非常庞大怎么管理,工具类的lib库管理等问题,就像设计房子的结构图
我们还需要设计一个简单的测试框架的架构,基于架构去填充自己的测试用例,架构如下:
- case目录
- 模块名目录_01
- 自动化case_01
- 自动化case_02
- 模块名目录_02
- lib目录
robotframework框架里定义的一个测试用例,就是一个以robot后缀结尾
的文件,通用的用例文件内容结构如下:
# -*- coding: robot -*-
*** Settings ***
Documentation 测试集合描述
Library ./lib/HttpLibrary.py
Library DateTime
Library json
Library Collections
*** Variables ***
${参数1}= xxx
${参数2}= yyy
*** Keywords ***
关键字名称
关键字逻辑
*** Test Cases ***
测试用例标题
[Tags] DEBUG
[Documentation] 测试用例描述
关键名称 ${参数1} ${参数2}
但在我们实际编写用例的时候,一个用例并不需要Settings
、Variables
、Keywords
、Test Cases
4个部分都包含,我们可以做一些调整,方便用例管理。具体的调整方法就是,创建一个base.robot
,这个用例文件没有具体的case逻辑Test Cases
这部分,而是将所有case需要用到的公有信息抽取出来,如需要引入的资源文件等等,这样做可以简化其余具体的case,去掉冗余信息
下面我以一个实际的接口测试自动化案例举例子,base.robot
内容如下:
# -*- coding: robot -*-
*** Variables ***
# 执行接口自动化的测试环境
${case_httpurl}= http://ip:port
${url_01}= api_01?param_1=xxx¶m_2=yyyy
${url_02}= api_02?param_1=xxx¶m_2=yyyy
${url_03}= api_03?param_1=xxx¶m_2=yyyy
${url_04}= api_04?param_1=xxx¶m_2=yyyy
&{cookies}= BDUSS=xxxx
*** Settings ***
Documentation xxx模块测试用例集合
Library ./lib/DictLibrary.py
Library ./lib/ListLibrary.py
Library ./lib/HttpLibrary.py
Library ./lib/LiveshowClientCommon.py
Library ./lib/ImLiveshowCommon.py
Library ./lib/DBOperation.py
Library ./lib/YamlSchemaValidatorLibrary.py
Library DateTime
Library json
Library Collections
*** Keywords ***
Init Base
[Documentation] 全局关键字初始化
${headers} Create Dict {"Content-type": "application/x-www-form-urlencoded"}
Create Http httpProxy ${case_httpurl} headers=${headers} cookies=&{cookies} timeout=500000
该base.robot
包含了Variables、Settings、Keywords三个部分,base.robot只是集成用例的公有信息,所以并没有Test Cases
这部分
在Variables中,我们定义了3种类型的变量,用来存放测试环境ip和端口、接口path以及cookies
Settings中则是引入lib目录下的工具类,这些工具类里面封装好了自定义参数,也可以引用python自带的工具库DateTime
、json
、Collections
等等。
Keywords中是定义了一个自定义关键字名叫Init Base,这个关键字用于初始化,Init Base关键字的逻辑共3行代码
先看一下第2行(如下图),Create Dict这个自定义关键字是从./lib/DictLibrary.py获取到的,为什么能获取到呢,因为我们在Settings部分用系统关键字Library已经导入该文件了,就和python导入包import
作用一样
${headers} Create Dict {"Content-type": "application/x-www-form-urlencoded"}
对于Create Dict的逻辑如下,传入value参数,经过json反序列化,返回字典类型。所以经过执行上面这段代码后,会给${headers}赋值一个字典类型
@keyword('Create Dict')
def create(value=None):
""" 创建一个字典值 """
if value is None:
return {}
if not isinstance(value, dict):
try:
value = eval(value)
except Exception as e:
pass
if not isinstance(value, dict):
try:
value = json.loads(value)
except Exception as e:
pass
if not isinstance(value, dict):
raise Exception('[关键字使用不正确] Create Dict 的参数需为 dict 格式')
return value
再看下Init Base关键字的第3行代码(如下图),Create Http是一个自定义关键字,从./lib/HttpLibrary.py获取到,传入了5个参数。这里注意一下robot case的变量定义,可以采用“变量标识符”($、@、&、%
)+大括号{}+变量名来表示,注意第一个参数,是一个字符串常量httpProxy,并不是一个变量
Create Http httpProxy ${case_httpurl} headers=${headers} cookies=&{cookies} timeout=500000
到这里base.robot的内容就讲完了,接下来我们看下具体的测试用例case该怎么写,用例代码如下
*** Settings ***
Documentation 用例描述
... author by yangzi
Force Tags 标签名
Resource base.robot
Suite Setup Init Base
*** Variables ***
${room_id}= ''
${im_sdk_version}= '7700016'
*** Test Cases ***
Normal Procedure
[Documentation] 用例描述
[Tags] P1
#获取参数
${params}= Create Dict {'room_id':${room_id},'im_sdk_version':${im_sdk_version}}
#发送请求,获取结果
${res}= Post Http httpProxy ${url_01} ${params}
# 打印log
log ${res}
Should Be Equal As Integers ${res.json()['errno']} 0 #成功
Validate With Yaml ./xxx.yaml ${res.json()}
这个robot case还是有3部分组成,分别是Settings、Variables、Test Cases。Settings部分使用Resource系统关键字导入base.robot,因为我们要使用到base.robot定义的关键字,Suite Setup也是一个系统关键字,即在执行该用例时,会首先运行此部分,这里我们看到是执行了Init Base关键字,这个关键字就是在base.robot里面定义的
在Test Cases部分,我们首先是组装了参数,然后执行Post Http关键字发送http请求,最后使用系统关键字Should Be Equal As Integers
进行结果断言,是否返回结果json当中errno
字段是否为0,而这里我们还用到了yaml文件去进行结果断言,yaml文件格式如下:
status: 0
errno: 0
msg: success
data:
msg: ''
user_cert:
status: !type_int
can_live: !type_int
user_type: !type_int
can_sale_goods: !py_def >
def judge_templateid(data):
if data in (0,1):
return True
return False
为什么要用yaml断言,是因为某些接口返回字段非常多或者返回字段是列表等等,不太方便直接在case当中直接断言
具体yaml文件的详细使用方法,以及上面使用到的Validate With Yaml
自定义参数逻辑,在以后的文章我会单独说明,一般情况下case断言我们使用系统关键字Should Be Equal As Integers或者Should Be Equal就行
执行用例仅需一条命令即可,常用命令如下:
#执行单个case,文件名mysql.robot
robot -P . ./demo/mysql.robot
#执行demo目录下所有case
robot -P . demo/
#执行当前目录下所有case
robot -P . ./
#执行当前目录下所有以robot后缀结尾的用例文件
robot -P . ./*.robot
命令解读
在执行完测试用例后,我们可以看到执行结果,看到pass就是case运行通过了
同时产生了三个测试报告,可使用浏览器打开。如果我们在编写测试用例时,使用了log关键字,测试报告里面也可以查看到,在case运行失败时,我们可以手动添加log进行调试,非常有用
好了,到这里恭喜你已经成功学会了Robot Framework的基本使用方法,本文主要介绍了使用Robot框架去进行接口自动化测试,同样Robot Framework可以结合Selenium、Appium做UI自动化,除此以外,本文还提到接口断言使用Yaml文件,介于篇幅太长,在以后的文章中,我会继续更新。另外本文涉及的代码涉及到公司敏感性,暂不开源,大家可以自己动动手实践
作为一个软件测试人员,除了手工测试外,还是非常有必要去掌握自动化测试,此篇文章凝结了真实企业级自动化测试实战经历,