!13 test01 Merge pull request !13 from cc1986746916/dev
QQ 529548204邮箱 529548204@qq.com如果有问题请联系我 大家共同学习共同进步~
2022年6月7日 更新 取消config中http类型 改为yaml数据内2022年5月30日 更新 YAML读取时间格式datetime数据后 json处理方式2022年5月20日 更新增加jenkins持续集成说明配置方法等2022年5月17日 更新增加xml参数处理,增加自定义加密方式(加密规则需要自己写 需要一定编码能力)
python 3.9 redis (存放用例数据) mysql (测试环境数据库) jdk allure 持续集成: docker jenkins
框架采用python的pytest模块, 搭配requests以及allure测试报告,可以发送钉钉通知邮件通知, 支持自定义接口加密,util.tools.encryption文件内自己编辑加密规则, 可以根据yaml测试数据自动生成用例, 支持接口关联, 支持类似jmeter的函数助手, 可以通过脚本进行接口录制,辅助编写yaml测试数据文件, 支持数据库断言, 支持分布式,jenkins持续集成。
|--接口自动化测试框架 # 主目录 ├─ common # 封装断言以及requests的方法 ├─ caches # 本地缓存保存路径 ├─ config # 配置文件读取 └─ config.ini ├─ testsuite # 测试相关文件 ├─ datas #测试数据 └─ 项目文件夹 名称同config中 testname一致 # 可以通过newproject脚本生成 └─ login.yml # 用例数据 格式参考下面YAML PARAM格式说明 ├─ testcase └─ 项目文件夹 名称同config中 testname一致 # 测试用例 可以通过writepage脚本生成 └─ test_login.py └─recording # 录制脚本文件夹放录制的接口文档 ├─ util # 常用工具 用例生成 接口录制 ├─ tools # 内部调用工具方法包含yaml读取 函数助手 数据库链接等 └─ scripts # 包含生成新项目,自动生成用例,接口录制 ├─ log # 日志 ├─ report # allure测试报告 ├─ pytest.ini # pytest配置 ├─ requirements.txt ├─ README.md └─ setupMain.py # 整体执行程序。
1. body 请求体内的参数中保存: body如果是 "id=2&path=haha" 会转换成字典 然后根据path使用jsonpath取值 2. response : 从json格式的响应结果中获取 3. cookies: 保存响应结果的cooies到本地
将需要替换为缓存数据的内容改成:$caches(cookies)$
$caches(cookies)$
示例:
cache: # 本地缓存 - cachefrom: 'body' path: '$.code' name: 'code' # 使用方法 需要的地方替换为$caches(code)$ - cachefrom: 'response' path: '$.data' name: 'data' # 使用方法 需要的地方替换为$caches(data)$ - cachefrom: 'cookies' path: # cookies 时path为空 name: 'cookies' # 使用方法 需要的地方替换为$caches(cookies)$
通过relevance字段来判断是否需要关联 如果不需要relevance字段为空即可
下面示例为 关联接口为tradeAdd 与 tradeAdd2两条yaml数据中case的第一条和第二条 分别去这两个接口返回结果的 id 并命名为tradeId 、tradeId2 内存中会保存成字典格式 {"tradeId":"10","tradeId2":"11"}读取方法:$relevance(tradeId2)$
{"tradeId":"10","tradeId2":"11"}
$relevance(tradeId2)$
relevance: response: - relCaseName: shangchuan # 其他testcase的ID relCaseNum: 1 # 关联的case数组里 第几条数据 reldata: - value: $.data.fileName # 当前返回结果的jsonpath name: fileName # 关联值名称 - value: $.data.policy # 当前返回结果的jsonpath name: policy # 关联值名称 - value: $.data.signature # 当前返回结果的jsonpath name: signature # 关联值名称 - relCaseName: tradeAdd2 # 其他testcase的ID relCaseNum: 2 # 关联的case数组里 第几条数据 reldata: - value: $.data.fileName # 当前返回结果的jsonpath name: fileName # 关联值名称 - value: $.data.policy # 当前返回结果的jsonpath name: policy # 关联值名称 - value: $.data.signature # 当前返回结果的jsonpath name: signature # 关联值名称
file : 通过case外关键字file判断是否需要上传文件 如果需要则格式为:{上传文件的参数名:文件路径}
file
{上传文件的参数名:文件路径}
param:包含两种请求格式(1)json格式 :{ "username": "finsiot","password": "$caches(pwd)quot; # 读取缓存值 }(同样适用于xml格式 会根据请求头application/xml或者text/xml 将字典转换成xml类型)(2)param格式username=admin&password=123
param
{ "username": "finsiot","password": "$caches(pwd)quot; # 读取缓存值 }
username=admin&password=123
urlparam为路径参数:{ id: 123 }
urlparam
{ id: 123 }
会根据字典转换成 路径参数 address中 v1/api/$url(id)$/中会根据id替换为123
v1/api/$url(id)$/
data: file: { files: D:\test\test.csv # 上传文件的参数名:文件路径 } param: { "username": "finsiot","password": "$caches(pwd)quot; # 读取缓存值 } urlparam: { id: 123 }# 路径参数 v1/api/$url(id)$/
jsonpath json格式数据断言: 根据json路径格式来获取实际结果同value中的预期结果进行判断 sqlassert 数据库结果断言 可同时判断多个结果值 根据sql中的查询语句查询出来的 第一条结果进行判断 time响应时间断言 默认为2秒 code http响应码断言
jsonpath
sqlassert
time
code
assert: jsonpath: - { "path": "$.data.expense_trend[0].peak_hour.peak_hour", "value": "123", # 预期结果 "asserttype": "==" # 判断相等 } - { "path": "$.code", "value": 0, "asserttype": "==" } - { "path": "$.data.id", "value": 196, "asserttype": "==" } sqlassert: # 如果不需要 此字段置空即可 - { "datas": [ { "path": "$.data.id", "name": "id" }, { "path": "$.data.username", "name": "username" }, ], "sql": "select * from saas.user where username = '****'", # 取数据库查询出的第一条数据进行验证 如果存在 列名 username 值为$.data.username则通过 "db_name": "database" # 判断链接那个数据库 } time: 2 # 响应时间断言 code: 200
部分数据采用faker库生成
int_num = "$RandomPosInt(1,333)quot; # 267 str_num = '$RandomString($RandomPosInt(2,23)$)$RandomPosInt(1,333)#39; # AbE3c14580f29aDFe5 float_num = '$RandomFloat($RandomPosInt(2,13)$,$RandomPosInt(2,13)$,$RandomPosInt(2,13)$)#39; # 11.84864 time_num = '$GetTime(time_type=else,layout=%Y-%m-%d %H:%M:%S,unit=0,0,0,0,0)#39; # 当前时间 2022-04-14 13:27:01 time_num2 = '$GetTime(time_type=future,layout=%Y-%m-%d %H:%M:%S,unit=0,0,0,3,0)#39; # 未来时间3天后 2022-04-17 13:32:42 time_num3 = '$GetTime(time_type=past,layout=%Y-%m-%d %H:%M:%S,unit=0,0,0,3,0)#39; # 过去时间3天前 2022-04-11 13:33:24 choice_num = '$Choice($RandomPosInt(2,13)$)#39; # 6 email = "$faker(email)quot;# 邮箱 # xkong@example.net idcard = "$faker(idcard)quot; # 130802196003197594 province = "$faker(province)quot; # 新疆维吾尔自治区 city = "$faker(city)quot; # 鹏市 phone_number = "$faker(phone_number)quot; # 15070673645 name = "$faker(name)quot; # 许云
使用场景: 新增数据A之后一系列用例执行完需要后置来还原数据形成业务闭环. datatype 有3种类型 param json 和urlparamdataname为后置关联的参数中参数名称path为当前请求返回结果的jsonpath 根据path的值更换后置处理参数值如果不需要后置处理 teardown 置空即可
teardown: - tdName: pointDel # 其他testcase的ID tdNum: 1 # 关联的case数组里 第几条数据 tddata: - datatype: param dataname: name path: $.name - datatype: urlparam dataname: pointId path: $.id - tdName: pointAdd # 其他testcase的ID tdNum: 1 # 关联的case数组里 第几条数据 tddata: - datatype: json dataname: name path: $.name - datatype: urlparam dataname: pointId path: $.id
!!!所有case的id 务必唯一!!!
name: "登录" # 测试用例模块名称 token: Authorization# 判断此接口是否使用token false 或者”cookie”或者”Authorization”等 如果不需要 置空或者填写false order: 1 用例执行顺序 @pytest.mark.run(order=1) # 因为此功能不支持分布式录制中已取消 file: bool值判断 true为此接口需要上传文件参数 case: 测试用例数据
name: "登录"
token: Authorization
order: 1
case
login: # caseID **请务必唯一** name: "登录" #测试用例模块 token: false # 判断此接口是否使用token false 或者"cookie"或者"Authorization"等 # token: "Authorization" order: 1 # 用例执行顺序 @pytest.mark.run(order=1) 因为此功能不支持分布式录制中已取消 file: true # bool值 true为需要文件的接口 case: - info: "用户名登录-成功" # 用例信息 http: https # http host: 'host' # config.ini里面 请求host的key address: '/v1/apps/$url(region_id)$/' # $url(region_id)$ 正则匹配参数中的路径参数 method: 'post' cache: # 本地缓存 # 保存本地缓存方法为3种 # 1. body 请求体内的参数中保存: # body如果是 "id=2&path=haha" 会转换成字典 然后根据path使用jsonpath取值 # 2. response : 从json格式的响应结果中获取 # 3. cookies: 保存响应结果的cooies到本地 - cachefrom: 'body' path: '$.code' name: 'code' # 使用方法 需要的地方替换为$caches(code)$ - cachefrom: 'response' path: '$.data' name: 'data' # 使用方法 需要的地方替换为$caches(data)$ - cachefrom: 'cookies' path: # cookies 时path为空 name: 'cookies' # 使用方法 需要的地方替换为$caches(cookies)$ # 接口关联 relevance: # 判断如果不需要关联relevance字段为空即可 # 如果需要关联就 response: # 场景 接口A删除请求,需要接口B新增请求中返回的ID以及name - relCaseName: pointAdd # 其他testcase的ID relCaseNum: 1 # 关联的case数组里 第几条数据 reldata: - value: $.id # 当前返回结果的jsonpath name: pointId # 关联值名称 - value: $.name # 当前返回结果的jsonpath name: pointname # 关联值名称 teardown: - tdName: pointDel # 后置请求的caseID tdNum: 1 # 后置请求的case数组里 第几条数据 tddata: - datatype: param dataname: name path: $.name - datatype: urlparam dataname: pointId path: $.id - datatype: json dataname: name path: $.name # 机制为 根据relevance字段生成字典{"tradeId":"123"} # 使用关联值方法为将需要替换的地方修改为 $relevance(tradeId)$ headers: { "Content-Type": "application/json" } data: file: { files: D:\test\test.csv # 上传文件的参数名:文件路径 } param: { "username": "finsiot","password": "$caches(pwd)quot; # 读取缓存值 } urlparam: { id: 123 }# 路径参数 v1/api/$url(id)$/ assert: jsonpath: - { "path": "$.data.expense_trend[0].peak_hour.peak_hour", "value": "123", "asserttype": "==" } - { "path": "$.code", "value": 0, "asserttype": "==" } - { "path": "$.data.id", "value": 196, "asserttype": "==" } sqlassert: # 如果不需要 此字段置空即可 - { "datas": [ { "path": "$.data.id", "name": "id" }, { "path": "$.data.username", "name": "username" }, ], "sql": "select * from saas.user where username = '****'", # 取数据库查询出的第一条数据进行验证 如果存在 列名 username 值为$.data.username则通过 "db_name": "database" # 判断链接那个数据库 } time: 2 # 响应时间断言 code: 200 # HTTP响应码断言
重点为[directory] 中的test_name 所有程序都围绕test_name 进行执行 根据testname来生成测试用例执行测试等
[directory] # 路径相关 log_dir = /logs data_dir = /datas page_dir = /page report_xml_dir = /report/xml report_html_dir = /report/html test_suite = /test_suite case_dir = /testcase cache_dir = /caches test_name = 测试项目名称: saasWeb [host] host = [email] ;服务器 mail_host = smtp.sina.com ;发送邮箱 mail_user = ;口令 mail_pass = ;发送者 sender = ;接收邮箱 receivers = [database] host = 192. port = 3306 user = root password = ;database = database = charset = utf8 [redis] host = 127.0.0.1 port = 6379 db = 1 password = 123456 charset = UTF-8 [dingding] webhook = secret =
1.代理设置设置计算机代理http=127.0.0.1:4444;https=127.0.0.1:4444;ftp=127.0.0.1:4444<-loopback>HTTPS:http://mitm.it/ 开启代理后下载证书安装执行脚本 recording.py 每个请求将会在 ./test_suite/recording 文件夹中建立文件 每次执行录制时会覆盖原文件
加签加密法: 在config中encryption增加sign的值 为签 需要在util.tools.encryption文件内自己编辑加密规则 需要加密的接口 YAML数据中encryption的值为true 会根据此在请求用例前增加加密装饰器
encryption
version: '3' services: jenkins: image: "jenkins_python" build: . depends_on: - redis container_name: jenkins volumes: - "/home/jenkins:/var/jenkins_home" ports: - "10240:8080" - "10241:50000" user: root links: - redis redis: image: "redis:alpine" container_name: redis restart: always volumes: - ../redis/redis.conf:/usr/local/etc/redis/redis.conf:rw - ../redis/data:/data:rw command: --requirepass "123456" ports: - "6379:6379" expose: - 6379
FROM jenkins/jenkins USER root ADD ./Python-3.9.7.tgz /var/python RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list RUN sed -i s@/security.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list WORKDIR /var/python3 RUN apt-get update \ && apt-get install -y vim\ && apt-get -y install gcc automake autoconf libtool make \ && apt-get -y install zlib* \ && apt-get -y install openssl libssl-dev \ && apt-get -y install sudo \ && apt-get install libffi-dev \ && apt-get install -y nodejs \ && /var/python/Python-3.9.7/configure --prefix=/var/python3 --with-ssl \ && make \ && make install \ && ln -sf /var/python3/bin/python3.9 /usr/bin/python \ && ln -sf /var/python3/bin/pip3 /usr/bin/pip \ && apt install npm -y \ && npm install -g allure-commandline --save-dev \ && /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone WORKDIR /
docker-compose up
Javahome路径 查询echo $JAVA_HOME 输出 /opt/java/openjdk
1 安装allure 和gitee插件
2 配置全局变量
3.新建autotest任务
4 增加构建步骤
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --default-timeout=1000 -r requirements.txt python setupMain.py
5 增加构建后操作allure报告
report/xml
点击高级
report/html
注意路径 相对workspace内任务的路径 前面没有斜线
注意路径 相对workspace内任务的路径 前面没有斜线Ubuntu文件编码有坑 项目yaml文档必须用utf-8编码
找到setipMain.py 红框内注意为当前jenkins建立的任务名称修改config.ini内redis配置 配置内容与docker容器保持一致 如密码
setipMain.py
注意 host 为dockercompose内link名称 内部链接采用redis:6379
这里给大家分享出来希望能和朋友们共同学习,共同进步 源码地址 https://gitee.com/a529548204/apitest
根据yaml自动生成测试用例脚本 支持sql断言 支持参数化 路径参数 支持数据关联 支持多种类随机数据生成 多种正则匹配 跨文件数据 关联支持分布式 使用redis收集测试用例 支持接口数据加密(测试版)
©Copyright 2023 CCF 开源发展委员会 Powered by Trustie& IntelliDE 京ICP备13000930号
接口自动化测试框架 pytest+ymal+allure+requests+redis
联系方式
QQ 529548204
邮箱 529548204@qq.com
如果有问题请联系我 大家共同学习共同进步~
更新日志
2022年6月7日 更新 取消config中http类型 改为yaml数据内
2022年5月30日 更新 YAML读取时间格式datetime数据后 json处理方式
2022年5月20日 更新增加jenkins持续集成说明配置方法等
2022年5月17日 更新增加xml参数处理,增加自定义加密方式(加密规则需要自己写 需要一定编码能力)
前言
环境要求
框架采用python的pytest模块, 搭配requests以及allure测试报告,可以发送钉钉通知邮件通知, 支持自定义接口加密,util.tools.encryption文件内自己编辑加密规则, 可以根据yaml测试数据自动生成用例, 支持接口关联, 支持类似jmeter的函数助手, 可以通过脚本进行接口录制,辅助编写yaml测试数据文件, 支持数据库断言, 支持分布式,jenkins持续集成。
注意
单用例调试时需要执行一次util\tools\readYamlFile.py将测试数据存入redis
一、目录结构
二、关键文件介绍
1.yaml测试数据格式
1.1 本地缓存介绍
保存本地缓存方法为3种
读取本地缓存方法
将需要替换为缓存数据的内容改成:
$caches(cookies)$
示例:
1.2 接口关联介绍
通过relevance字段来判断是否需要关联 如果不需要relevance字段为空即可
示例:
下面示例为 关联接口为tradeAdd 与 tradeAdd2两条yaml数据中case的第一条和第二条 分别去这两个接口返回结果的 id 并命名为tradeId 、tradeId2 内存中会保存成字典格式
{"tradeId":"10","tradeId2":"11"}
读取方法:
$relevance(tradeId2)$
1.3 参数介绍
file
: 通过case外关键字file判断是否需要上传文件 如果需要则格式为:{上传文件的参数名:文件路径}
param
:包含两种请求格式(1)json格式 :
{ "username": "finsiot","password": "$caches(pwd)quot; # 读取缓存值 }
(同样适用于xml格式 会根据请求头application/xml或者text/xml 将字典转换成xml类型)(2)param格式
username=admin&password=123
urlparam
为路径参数:{ id: 123 }
会根据字典转换成 路径参数 address中
v1/api/$url(id)$/
中会根据id替换为1231.4 断言介绍
jsonpath
json格式数据断言: 根据json路径格式来获取实际结果同value中的预期结果进行判断sqlassert
数据库结果断言 可同时判断多个结果值 根据sql中的查询语句查询出来的 第一条结果进行判断time
响应时间断言 默认为2秒code
http响应码断言1.5 生成随机数据介绍
部分数据采用faker库生成
1.6 后置请求处理
使用场景: 新增数据A之后一系列用例执行完需要后置来还原数据形成业务闭环. datatype 有3种类型 param json 和urlparam
dataname为后置关联的参数中参数名称
path为当前请求返回结果的jsonpath 根据path的值更换后置处理参数值
如果不需要后置处理 teardown 置空即可
三、文件展示
3.1yaml文件展示
name: "登录"
# 测试用例模块名称token: Authorization
# 判断此接口是否使用token false 或者”cookie”或者”Authorization”等 如果不需要 置空或者填写falseorder: 1
用例执行顺序 @pytest.mark.run(order=1) # 因为此功能不支持分布式录制中已取消file
: bool值判断 true为此接口需要上传文件参数case
: 测试用例数据3.2 config.ini配置文件格式
四、接口录制
1.代理设置
设置计算机代理
http=127.0.0.1:4444;https=127.0.0.1:4444;ftp=127.0.0.1:4444
<-loopback>
HTTPS:
http://mitm.it/ 开启代理后下载证书安装
执行脚本 recording.py 每个请求将会在 ./test_suite/recording 文件夹中建立文件 每次执行录制时会覆盖原文件
五、接口加密(测试版)
加签加密法: 在config中
encryption
增加sign的值 为签 需要在util.tools.encryption文件内自己编辑加密规则 需要加密的接口 YAML数据中encryption的值为true 会根据此在请求用例前增加加密装饰器六、操作方法
七、代码展示
test_login.py login.yml conftest.py八、jenkins集成
8.1 docker环境搭建:
1 安装docker(不会请百度)2 新建任意文件夹
3 新建文件 Dockerfile 4 新建文件docker-compose.yml
5 复制python安装包 文件内容如下:
docker-compose.yml Dockerfile 在文件目录内执行命令
docker-compose up
这样生成了两个容器 一个是包含allure和python的jenkins容器和一个redis容器8.2jenkins配置
Javahome路径 查询echo $JAVA_HOME 输出 /opt/java/openjdk
1 安装allure 和gitee插件
2 配置全局变量
3.新建autotest任务
4 增加构建步骤
5 增加构建后操作allure报告
report/xml
点击高级
report/html
注意路径 相对workspace内任务的路径 前面没有斜线
8.3注意事项
注意路径 相对workspace内任务的路径 前面没有斜线
Ubuntu文件编码有坑 项目yaml文档必须用utf-8编码
8.4脚本代码更改
找到
setipMain.py
红框内注意为当前jenkins建立的任务名称
修改config.ini内redis配置 配置内容与docker容器保持一致 如密码
注意 host 为dockercompose内link名称 内部链接采用redis:6379
总结
这里给大家分享出来希望能和朋友们共同学习,共同进步 源码地址 https://gitee.com/a529548204/apitest