【Robot Framework 】项目实战汇总
写在前面
RF自动化的文章记录基本完成,建一个汇总目录,方便查看。
【Robot Framework 项目实战】汇总
∮【RF 项目实战 01】使用 RequestsLibrary 进行接口测试
∮【RF 项目实战 03】使用脚本自动生成统一格式的RF自动化用例
∮【RF 项目实战 04】基于录制生成RF关键字及基础自动化用例
脚本优化
上一篇博客我们编写了基于录制生成的RF自动化Demo用例,但是只是完全根据抓包数据构造了一条正常的测试用例,其实针对接口的参数校验这样的重复性比较强的测试,我们也可以把它们脚本化,参数化到RF文件中。
接口测试,基本参数校验范围
基本参数校验,是每次接口测试首要考虑的内容,这部分应当是测试工程师的基本能力。
- 可选与必选:
- 字段可选,传与不传时的区别
- 字段必选,必选参数缺失时返回什么错误,返回格式是否标准
- 空值:
- 空值时,返回什么结果。(如网络超时未返回,当成空值在处理还是默认值处理)
- 默认值:
- 是否有默认值,可选参数和必选参数是否有默认值
- 类型:
- int,区分32和64位,int类型时,传str时的错误展示
- string类型,
- float类型,往往在计算金额时,会用到浮点数
- 类型长度:
- 超过长度,接口请求是否出错,如果不出错,展示是否被截断
- 中文跨越边界时被截断的问题,如nickname是32字节,共16个中文,前15是中文,第16是英文,第17是中文,则多出一个字节,最后一个中文是否被截断显示为乱码
- 大小写:
- 是否大小写敏感,signkey,等内容,一般大小写敏感
- 安全过滤:
- <>是否被过滤掉,是否有直接存写到DB
- ' " 是否被转译或者使用防SQL注入的ORM组件
- 编码类型:
- utf-8,GBK,unicode
- 特殊字符(空格,换行等),emoji(4个字节),中文,拉丁文,日文等
具体实现
首先我们定义一批可能需要传递的参数,使用常量的方式存储。
PARAM_ERR = 10000
OK = 0
BOOL = True # False
INT = 10
NEG_INT = -1
ZERO = 0
BIG_INT = 99**5
NEG_FLOAT = -1.1
FLOAT = 0.99
EMPTY_STR = ""
INT_STR = "1111"
LETTERS_STR = "ABCabc"
SPACE_STR = " "
EMPTY_LIST = []
STR_LIST = ["a", "b"]
INT_LIST = [10, 20]
BOOL_LIST = [True, False]
MIX_LIST = ["a", True, 10, ["aa"], {"a": "aa"}]
EMPTY_DICT = {}
STR_DICT = {"a": "b"}
INT_DICT = {"d": 11}
BOOL_DICT = {"c": True}
MIX_DICT = {"b": "", "c": True, "d": 11, "e": {"f": [1, 2]}}
...
然后我们通过原始的请求参数,自己组装不同的请求参数:
def gen_req_data(sheet_obj):
str_params = sheet_obj.cell_value(1, 1)
str_method = sheet_obj.cell_value(1, 6)
temp_list = []
# print(f"str_params:{str_params}")
if not len(str_params):
return ""
try:
# 转化 json类型为Python标准类型
params = eval(str_params.replace("false", "False").replace("true", "True").replace("null", "None"))
if not len(params):
return ""
except Exception as f:
logger.warning("====================================================")
logger.error("=" + str(f))
logger.warning("====================================================")
params = ""
# 正常参数
temp_list.append(params)
# 添加异常参数
for k, v in params.items():
if isinstance(v, dict):
for i in [
BOOL,
NEG_FLOAT,
LETTERS_STR,
MIX_LIST,
ZERO,
MIX_DICT
]:
params = copy.deepcopy(params) # 深拷贝,字典存储的是内存地址
params[k] = i # doc
temp_list.append(params)
elif isinstance(v, list):
for i in [BOOL, NEG_FLOAT, LETTERS_STR, MIX_LIST, ZERO, MIX_DICT]:
params = copy.deepcopy(params)
params[k] = i
temp_list.append(params)
elif isinstance(v, str):
for i in [BOOL, NEG_FLOAT, EMPTY_STR, INT_STR, SPACE_STR, MIX_DICT, STR_LIST, EMPTY_DICT]:
params = copy.deepcopy(params)
params[k] = i
temp_list.append(params)
elif isinstance(v, int):
for i in [BOOL, NEG_FLOAT, INT_STR, INT_LIST, NEG_INT, ZERO, BIG_INT, NEG_FLOAT, FLOAT, EMPTY_DICT]:
params = copy.deepcopy(params)
params[k] = i
temp_list.append(params)
elif isinstance(v, bool):
for i in [True, False, ZERO, FLOAT, NEG_INT, INT_STR, INT_LIST, STR_DICT]:
params = copy.deepcopy(params)
params[k] = i
temp_list.append(params)
return str_method, temp_list
最后,我们把不同的请求参数转化为RF测试用例需要的数据格式,最终生成对应的测试用例:
def gen_testcase(self, sheet_obj, target_robot_name, interface_name):
"""
:param sheet_obj:
:param target_robot_name:
:param interface_name:
:return:
"""
method, params_list = self.gen_req_data(sheet_obj)
with open(target_robot_name, 'a') as f:
for num, param in enumerate(params_list):
"""
待办:动态修改Documentation的信息,异常参数以tuple的形式存储Documentation,然后解析的时候参数化到文档中
"""
f.write(interface_name + f'.Demo_case{num}' + '\n')
f.write(' [Documentation] demo' + '\n')
f.write(' [Tags] ' + self.tag + '\n')
params = self._gen_param_data(method, param)
f.write(params)
if params:
f.write(' ${{Resp_data}} {}'.format(self.project_abbr) + interface_name + ' ${HOST} ' + "${param}")
else:
f.write(' # 未获取到请求参数数据 \n')
f.write(' ${{Resp_data}} {}'.format(self.project_abbr) + interface_name + ' ${HOST} ' + "${EMPTY}")
f.write('\n')
f.write(' Log ${Resp_data.text}' + '\n')
# 第一条用例正常断言,其他用例标记为失败用例
if num == 0:
f.write(' Should Be Equal As Strings ${Resp_data.status_code} 200' + '\n')
f.write(' ${resp_json} to json ${Resp_data.text}' + '\n')
f.write(self.gen_exp_data(sheet_obj))
else:
f.write(f' Should Be Equal As Strings ${{Resp_data.status_code}} {self.error_status_code}' + '\n')
f.write(' ${resp_json} to json ${Resp_data.text}' + '\n')
f.write(self._format_exp_data(self.param_error_json)) # param_error_json 接口异常返回内容中的公共部分,比如code, result
f.write('\n')
logger.info("Demo case保存于:" + target_robot_name)
注:⚠️ 部分依赖代码在上一篇文章中可以找到。
总结
通过抓包,我们获取了原始数据,然后根据抽象异常参数传递校验的方式,把接口测试异常用例抽取了出来,这个不管是在手工测试过程中,还是在自动化过程中都非常的有用,能节省大量的人力成本。
当然这个方式也有一定的局限性,需要整个团队来配置,比如脚本中使用到的param_error_json就是因为博主所在项目组有比较规范的接口返回定义才能做这样的统一断言。
【Robot Framework 】项目实战汇总的更多相关文章
- 【Robot Framework 项目实战 01】使用 RequestsLibrary 进行接口测试
写在前面 本文我们一起来学习如何使用Robot Framework 的RequestsLibrary库,涉及POST.GET接口测试,RF用例分层封装设计等内容. 接口 接口测试是我们最常见的测试类型 ...
- 【Robot Framework 项目实战 00】环境搭建
前言 我们公司在推广RF这个框架做后端接口测试,力求让同事们能更快的完成服务端需求的自动化,作为主导者之一,决定分享一些经验,方便后来者. 我会从安装部署.Request.selenium.自定义框架 ...
- 【Robot Framework 项目实战 02】SeleniumLibrary Web UI 自动化
前言 SeleniumLibrary 是针对 Robot Framework 开发的 Selenium 库.它也 Robot Framework 下面最流程的库之一.主要用于编写 Web UI 自动化 ...
- 【Robot Framework 项目实战 03】使用脚本自动生成统一格式的RF自动化用例
背景 虽然大家都已经使用了统一的关键字,但是在检查了一些测试用例之后,还是发现因为大家对RF的熟悉程度不一导致的测试用例颗粒度差异很大的情况:而且在手动方式转化测试用例过程中,有不少工作是完全重复的且 ...
- 【Robot Framework 项目实战 02】使用脚本生成统一格式的RF关键字
背景 在微服务化的调用环境下,测试数据及接口依赖的维护是一个问题,因为依赖的接口和数据可能不在同一个服务下,而这相关的多个服务往往是不同人员来测试的. 因此为了节省沟通成本,避免关键字的重复冗余.所以 ...
- 【Robot Framework 项目实战 04】基于录制,生成RF关键字及 自动化用例
背景 因为服务的迁移,Jira版本的更新,很多接口文档的维护变少,导致想要编写部分服务的自动化测试变得尤为麻烦,很多服务,尤其是客户端接口需要通过抓包的方式查询参数来编写自动化用例,但是过程中手工重复 ...
- Robot Framework 项目搭建
首先新建一个项目“RobotDemo".项目Type一般选择“Directory”形式. 项目第一层可以放3种文件:Test Suite.Directory 和 Resource File. ...
- Robot Framework 学习资源汇总
学习网站 http://robotframework.org/ http://www.testtao.cn/?cat=43 https://www.jianshu.com/c/483e8ffcbc79 ...
- 自动化测试框架Cucumber和Robot Framework的实战对比
自动化测试框架Cucumber和RobotFramework的实战对比 一.摘要 自动化测试可以快速自动完成大量测试用例,节约巨大的人工测试成本:同时它需要拥有专业开发技能的人才能完成开发,且需要大量 ...
随机推荐
- SQL递归查询(with as)
SQL递归查询(with cte as) with cte as( select Id,Pid,DeptName,0 as lvl from Department where Id = 2 ...
- Python练习_购物车_day6
第一次代码 (1) 输出商品列表,用户输入序号,显示用户选中的商品. 页面显示 序号 + 商品名称,如: 1 手机 2 电脑 (2): 用户输入选择的商品序号,然后打印商品名称 (3):如果用户输入的 ...
- Python考试_第三次
- python 全栈11期月考题 一 基础知识:(70分) 1.文件操作有哪些模式?请简述各模式的作用(2分) 2.详细说明tuple.list.dict的用法,以及它们的特点(3分) 3.解释生成 ...
- 2、JDK8中的HashMap实现原理及源码分析
本篇提纲.png 本篇所述源码基于JDK1.8.0_121 在写上一篇线性表的文章的时候,笔者看的是Android源码中support24中的Java代码,当时发现这个ArrayList和Linked ...
- Python函数知识点总结
1.函数的定义2.如何定义一个函数以及函数语法3.函数的调用4.函数的参数(形参,实参)以及参数的传递5.函数的返回值6.变量的作用域7.匿名函数8.嵌套函数和闭包9.装饰器10.函数思维导图 1.函 ...
- gradient 渐变
看了大漠 写的关于 Gradient 的文章,我也想写点以便加深记忆. 首先gradient 分为linear-gradient (线性渐变) 和 radial-gradient(径向渐变),渐变是作 ...
- elementui 树控件只隐藏第三集菜单
<!-- 必须属性:default-expanded-keys node-key --> <el-tree :default-expanded-keys='idArr' node-k ...
- vue cli3 打包到tomcat上报错问题
首先 项目打包步骤 1.vue config.js 添加 publicPath: './', // 公共路径 assetsDir:'static', 2.将代理注释掉 proxy 3.将hash需 ...
- (详细)JAVA使用JDBC连接MySQL数据库(3)-代码部分
欢迎任何形式的转载,但请务必注明出处. 本节主要内容 项目建立 数据库连接 数据库操作 主函数 点击进入推荐博客(必看) 一.项目建立 如图所示:新建Java Project.Package.Clas ...
- mysql 创建用户,授权,查询用户等
MySQL创建用户与授权 一. 创建用户 命令: CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明: username:你将创建的用 ...