博主之前的工作中使用过Python+robotframework框架进行接口自动化和webUI自动化,现在按照自己的过往经验,搭建python+pytest+allure的接口自动化框架。
很多人会python、requests、json等库去发送请求并处理请求,但是有些人还是不知道接口自动化要怎么做。我个人认为搭建框架最重要的是规范化管理,比如接口数据存放在哪里?脚本如何管理等,当大家都按照规范去实现的时候,后续就比较容易维护和管理,项目的自动化就会走得长远一些。
本人搭建的python+pytesst+allure的自动化框架代码:
https://gitee.com/wenxiaoba/interface_test.git
(PS:在main分支上)
这个是一个基础的框架,其实使用起来还有很多问题,比如日志不详细,只能发送http请求等,这些可以根据需要自己去优化,也可以在评论区中提供建议,我有空也会去更新~
使用示例
现在先以一个简单的例子介绍怎么使用。
接口信息:
- url:https://httpbin.org/get
- method:GET
- 请求参数:{“name”: “xxx”, “id”: xxx}
项目路径配置
pytest命令执行终端不一样的话,Python读取库的路径也不一样,但是框架搭建时,一些脚本的导入是以当前项目根目录的方式去导入的,所以需要将当前项目根目录添加到python的识别路径中,我是window系统,在python的安装目录/Lib/site-packages下,将项目根目录路径添加到.pth文件中,如下:
接口信息配置
我们根据项目的系统将接口归类到httpbbin系统(一个项目可能有多个系统),我们先去InterfaceData/httpbbin.yaml配置接口信息,如下:
我们将接口取名为“Get请求”(在用例层面使用这个名称);
请求方式method为“get”;
url(https://httpbin.org/get)被分成2部分,一个是接口域名,一个是接口路径,Get请求下的url存放的是接口路径,即“/get”;
interface字段可以理解为该接口的英文名称(当前系统必须唯一),后续的请求报文拼装脚本和接口数据校验脚本的脚本名称保持与interface字段值一致。
由于一个系统的有多个接口,大部分接口的域名都一致,所以统一在另一个文件管理,即system字段会映射到另一份配置文件(当前文件httpbin.yaml也是“<系统名称>.yaml”),该文件管理接口域名,如下:
即如果有新的接口域名,必须在SystemConfig目录对应的环境配置文件中进行配置,否则接口url拼接会失败。
接下来就是接口请求数据的配置,即请求模板,
需要告诉程序请求报文如何拼接
用例编辑
get_request_data()方法说明
获取到完整的请求url和请求报文后,发送请求数据,框架是通过utils.Transaction的get_request_data()方法去发送http请求的。如下图,我们可以看到get_request_data()方法需要传入的参数有:
- interface_name:接口的中文名称,与config/InterfaceData/httpbin.yaml中配置的中文名称保持一致。
- update_datas:字典类型,在拼装请求报文时,会先去获取请求模板(config/RequestTemplate/httpbin/GetRequest.json),在根据传入update_datas字典数据,去更新请求模板中的字段值。
- delete_keys:请求模板是包含了全部字段,有时候测试必须/非必须的场景时,可以将字段名称添加到列表中,如果字段名称在delete_keys中,则请求报文中不会出现该字段。
用例编写
在testcases/cases下编写测试用例,按照项目的维护情况保存,我们从test_get.py中的2个用例可以看到,发送请求用的就是utils.Transaction对象的get_request_data()方法
数据校验
发送完请求之后,我们需要进行数据校验,如响应报文校验和数据库数据校验。
在测试用例层面,如果需要进行数据校验,则可通过utils.Transaction对象的compare_data()方法去校验。
通过pytest命令(pytest --alluredir ./report)执行用例后,查看allure报告,如下:
一个用例编写完成了,接下来就介绍一些具体的内容。
框架介绍
框架搭建结构目录如下:
- common:存放接口数据拼装、响应数据比对的脚本。
- config:存放接口数据模板和一些系统配置信息。
- report:存放用例执行结果数据
- testcases:存放测试用例和执行数据
- utils:一些公共功能的脚本实现。
环境切换
我们测试的时候是会有多套环境的,框架需要实现随着环境的切换,其url、测试数据等能随着切换。
环境切换是在testcases/datas/env.py中进行切换的,如下图,env = "test"
表示切到test环境,为dev
表示切到开发环境。env.py中的env值需要与config/SystemConfig下的文件名称保持一致,否则会报错(接口域名获取失败)。
报错原因:接口域名是根据环境变量去获取的,如果环境变量env赋值错误,则接口域名会获取失败,如下:
不同的环境,其同一特征的测试数据是不同的,比如在测试环境,符合某个特征的是A用户,但是在开发环境,符合的是B用户,切换环境的时候,我们希望只需要切换环境,不需要按照不同的环境去维护不同的测试用例,所以测试数据也能随着环境切换而切换,测试数据是维护在testcases/datas/case_use_datas下的,如下dev环境和test环境的数据:
在用例层面,如果想实现随着环境切换同步切换数据的效果,则需要在对应的用例上共享init_datas(),具体使用如下:
init_datas()是在conftest.py中实现的,可扩展。
交易对象Transaction(管理请求)
交易对象Transaction主要是管理请求,比如请求数据的拼装、发送请求、数据校验等,并保存相关的数据(请求报文、响应报文),如果所有系统有共同的请求逻辑,可以在这里修改实现。
字典数据比对JsonDataCompare(管理请求)
JsonDataCompare(().compare_data(expect_data, actual_data)
是以expect_data为基准,确认actual_data对应的数据是否符合标准,比对结果会将比对成功的字段放入成功序列,将比对失败的字段放入失败序列,若字段在actual_data中不在expect_data中,则该字段列入不必对序列,只要失败序列有值,则总体比对失败,并且会在allure报告中显示比对情况,如下:
(PS:字段的名称是遵循了一定规律的,如果值是子字典,则通过.
连接,如果值是列表、元组等类型,则通过[下标值]]
连接,如headers.Host表示当前字典的headers字段值是一个字典,该字典有个Host字段,如果是headers.Host[0]表示headers.Host字段值是一个列表,[0]表示是第一个列表值)
如果字段是字符串行驶,还提供了正则表达式的比对方式,只要预期值设置为re.正则表达式
,如下:
数据库操作SqlOperates
除了比对响应报文,也需要去比对数据库的数据,SqlOperates也提供了数据库查询操作(也可以增删改)(暂时只实现了MySQL的,其他的可以根据需要优化)。
数据库信息在config/SystemConfig对应环境配置文件中维护,如下:
操作数据库时,调用SqlOperates的类方法execute_sql(db_name, sql)
,db_name就是在config/SystemConfig配置的系统名称,如"student"或"httpbin"等,使用如下: