接口自动化框架搭建总结
1 框架设计思路
目标:参考HttpRunner
框架,约定大于配置,测试人员只需要维护Yaml
文件即可进行接口自动化测试,在Yaml
文件中进行参数化、接口前置处理、接口后置处理、断言等。
核心功能点:
- 支持对多项目、多环境进行配置
- 对
Yaml
文件的读取进行封装 - 对
Requests
请求进行封装 - 单个
Yaml
文件中支持单接口、多接口场景 - 支持参数池,接口请求发送之前参数调用参数池进行值替换
- 支持自定义参数池
- 支持
hook
,接口请求发送前后支持调用hook
函数 - 支持
allure
报告 - 支持运行日志记录
- 支持
Yaml
文件规范性检查 - 支持邮件发送测试结果
- 支持
Swagger
文档转为Yaml
用例 - 支持
SQL
前后置,运行sql进行断言,从sql结果中取参数,运行sql - 支持多种断言方式
- 控制是否运行
- 控制睡眠时间
2 第三方依赖
1 | # 单元测试框架 |
3 知识点
3.1 Yaml
读取封装
- 进行读、覆盖写、追加写、清空等方法封装
1 | class YamlUtil: |
3.2 接口请求封装
- 保持会话,在不同的接口请求之间保持会话的一致
- 不管是
get
还是post
方法,在requests
库中最终都调用了request
方法。所以这里使用request
方法,以**kwargs
关键字参数来接受一个字典,思路就是对Yaml
文件中的接口请求信息进行处理,将处理好的接口请求信息组装成一个字典,然后调用request
方法进行接口请求的发送。
1 | # 封装的代码 |
3.3 文件上传处理
如果
Yaml
中的键包含files
,那么就需要进行文件上传处理Yaml
文件中的file
是文件上传接口中的请求参数名称,若该接口中名称不是file
则需要在Yaml
中进行对应的更换调整支持多文件同时上传,单个/多个文件路径都写在列表中
文件上传的处理包括了单字段发送单个文件、单字段发送多个文件、字典形式发送、元组列表形式发送等
框架中采用的时单字段发送多个文件,使用的元组列表形式如下:
1 | [ |
1 | - |
1 | class RequestUtil: |
3.4 Yaml
文件编写
config:配置文件
- variables:变量,自定义函数/参数替换后存入参数池
teststeps:测试步骤,可以是单个步骤(单用例),页可以是多个步骤
epic:项目名称
feature:接口所属模块
story:接口名称
title:用例名称
requests:接口请求信息
- url:接口路径
- method:接口访问方式
- headers:接口请求的header信息,字典格式
- params:URL中的参数
- data:接口请求的data信息
- json:接口请求的json信息
- files:文件上传的文件路径,需要把路径写在列表里面
setup_hooks:前置钩子,在请求发送之前执行
teardown_hooks:后置钩子,在请求发送之后执行
headers_extract:从接口响应header中提取参数并放入参数池,字典格式
extract:从接口响应信息中提取参数并放入参数池,使用jsonpath格式
validate:断言,字典格式
1 | config: |
3.5 自定义函数
- 在
Yaml
的requests
信息中,如果包含有${__()}
格式的字符串,则说明该字符串是调用一个方法 - 传入一个
json
格式的字符串,通过正则表达式,从字符串中找到所有符合格式的函数名称,如${__getNum(1,2)}
则匹配的结果就是[(getNum,'1,2')]
- 通过反射来获取对象属性,使用
getattr(obj, 'value')
函数获取对象的属性,这里设置obj
为hook
函数的代码编写所在类的实例化对象,value
为方法名称,获取到对象属性后,利用()
来执行该方法,若存在参数,则通过,
来进行字符串分割,分割后是一个参数组成的元组,使用*args
可变参数来接受这个元组
1 | # 传入用例数据,json格式的字符串,传入的是用例的requests中的内容 |
3.6 前置参数替换
- 在
Yaml
的requests
信息中,如果包含有${}
格式的字符串,则说明该字符串需要进行参数处理 - 传入json格式的字符串,定义正则表达式来提取出参数名称,提取出来的结果是一个列表
- 先从环境变量中找是否有该参数,如果有,则从环境变量中取值,如果没有就从参数池中进行取值,参数池中也没有的话就不进行替换
- 将替换后的字符串进行返回,进入下一流程处理
1 | # 参数化替换 |
3.7 后置参数提取
- 在
Yaml
的信息中,如果包含有extract_key
关键字,则说明需要进行接口响应数据的提取 jsonpath
解析后的数据是数组,所以要用下标0
来取值- 将提取的数据存入参数池中
1 | # 响应数据处理 |
3.8 找到项目下的Yaml
文件、转为pytest
用例
- 存在多个项目的情况下,可指定运行某一个项目,每个项目都是一个目录,目录名称就是项目名称,项目名称目录下可嵌套多级目录,最后一级是
Yaml
文件 - 使用
glob
模块递归查询data
下面的项目目录下的所有以.yaml
为后缀的文件 - 利用反射
setattr
向pytest
测试类中注入方法,方法名以test_
+Yaml
文件名进行命名,方法的内容就是test_case
方法中的内容
1 | # 传入要运行的项目文件名称 |
3.9 处理Yaml
文件中多个接口
- 利用
pytest
中的@pytest.mark.parametrize
来进行参数化,get_case_info
返回的是由多个字典格式的接口数据组成的列表,由参数化来取得每一个接口的字典数据
1 | # 传入yaml文件路径,获取该yaml里面的全部信息 |
3.10 用例格式
1 | config: |
1.1 json转换
1 | # 将字典转为json格式字符串 |
1.2 jsonpath
1 | # jsonpath执行后返回的是数组 |
1.3 反射
1 | # 通过attr获取到对象的属性/方法,即有了方法名称就可以执行到对应的方法 |