更多学习资料请加QQ群: 822601020获取

实现效果

需求场景:

  1. 公司微服务接口使用数字签名的方式, 使用Postman调试接口每次都需要修改源码将验签临时关闭, 但是关闭后,其他微服务不能正常调用该服务
  2. 从ELK中抓取到的接口参数, 需要Json格式化, 我通常使用Sublime Text + PrettyJson插件, 使用Postman调试, 有些表单类接口, 还需要把每个参数及值复制出来, 特别麻烦.

实现原理:

  • Sublime text3可以自定义编译系统
  • Python方便的json数据处理
  • 使用Python实现签名算法
  • requests发送接口请求

实现目标:

  • 采用json文件数据驱动, 支持一个json包含多个接口
  • 支持GET/POST/DELETE/...方法
  • 支持表单类/Json类请求
  • 支持headers, cookies, params, data, files, timeout
  • 支持session依赖, 中间变量

数据文件格式:

  • Get请求
{
"url": "http://127.0.0.1:5000/api/user/logout/?name=张三"
}

{
"url": "http://127.0.0.1:5000/api/user/logout/",
"params": {"name": "张三"}
}
  • Post表单请求:
{
"url": "http://127.0.0.1:5000/api/user/login/",
"data": {"name": "张三","password": "123456"}
}
  • Json格式请求:
{
"url": "http://127.0.0.1:5000/api/user/reg/",
"headers": {"Content-Type": "application/json"},
"data": { "name": "张991", "password": "123456"}
}

{
"url": "http://127.0.0.1:5000/api/user/reg/",
"type": "json",
"data": { "name": "张991","password": "123456"}
}
  • 断言格式(ASSERT):
{
"url": "http://127.0.0.1:5000/api/user/login/",
"data": {"name": "张三","password": "123456"},
"ASSERT": ["response.status_code == 200", "'成功' in response.text"]
}
  • 需要签名(SIGN):
{   "url": "http://127.0.0.1:5000/api/user/delUser/",
"type": "json",
"data": {"name": "张三"},
"SIGN": true
}
  • 多接口,session依赖, 及中间变量(STORE)
[
{
"url": "http://127.0.0.1:5000/api/user/getToken/",
"method": "get",
"params": {"appid": "136425"},
"STORE": {"token": "response.text.split('=')[1]"}
},
{ "url": "http://127.0.0.1:5000/api/user/updateUser/?token=%(token)s",
"headers": {"Content-Type": "application/json"},
"data": {"name": "张三","password": "123456"}
}
]

工具实现:

sign.py

import hashlib

appid = user
appsecret = NTA3ZTU2ZWM5ZmVkYTVmMDBkMDM3YTBi def md5(str):
m = hashlib.md5()
m.update(str.encode('utf8'))
return m.hexdigest() #返回摘要,作为十六进制数据字符串值 def makeSign(params):
if not isinstance(params, dict):
print("参数格式不正确,必须为字典格式")
return None
if 'sign' in params:
params.pop('sign')
sign = ''
for key in sorted(params.keys()):
sign = sign + key + '=' + str(params[key]) + '&'
sign = md5(sign + 'appsecret=' + appsecret)
params['sign'] = sign
return params

post_json.py

import json
import os
import requests
from sign import makeSign timeout = 10 def postJson(path, timeout=60):
try:
with open(path, encoding='utf-8') as f:
apis = json.load(f)
except IOError as e:
print(e) except json.decoder.JSONDecodeError:
print("json文件格式有误") if isinstance(apis, dict):
apis=[apis] session = requests.session()
for api in apis: # 处理全局变量
str_api = json.dumps(api)
if '%' in str_api:
api = json.loads(str_api % globals()) # 获取接口相关项
url = api.get('url')
method = api.get('method')
type = api.get('type')
headers = api.get('headers')
cookies = api.get('cookies')
params = api.get('params')
data = api.get('data')
files = api.get('files') # 特定动作(系统标签)
_sign = api.get('SIGN') # 对数据进行签名
_store = api.get('STORE') # 存储变量
_assert = api.get('ASSERT') # 结果断言 # 处理签名
if _sign:
data = makeSign(data) # 如果json请求,转换一下数据
if type and type == 'json' or headers and 'json' in json.dumps(headers):
data = json.dumps(data) # 根据method发送不同请求
if not method or method.lower() == 'post': # 有data字段默认使用post方法
response = session.post(url=url, headers=headers, cookies=cookies, params=params, data=data, files=files, timeout=timeout)
elif not data or method.lower() == 'get': # 没有data字段默认采用get方法
response = session.get(url=url, headers=headers, cookies=cookies, params=params, timeout=timeout)
elif method.lower() == 'delete':
response = session.delete(url=url, headers=headers, cookies=cookies, params=params, data=data, files=files, timeout=timeout)
elif method.lower() == 'put':
response = session.put(url=url, headers=headers, cookies=cookies, params=params, data=data, files=files, timeout=timeout)
elif method.lower() == 'patch':
response = session.patch(url=url, headers=headers, cookies=cookies, params=params, data=data, files=files, timeout=timeout)
elif method.lower() == 'head':
response = session.head(url=url, headers=headers, cookies=cookies, params=params, data=data, files=files, timeout=timeout)
else:
print("不支持当前方法") # 存储中间结果
if _store:
for key in _store:
globals()[key]=eval(_store[key]) # 处理响应
try:
response_text = json.dumps(response.json(), ensure_ascii=False, indent=2)
except json.decoder.JSONDecodeError: # only python3
try:
response_text = response.text
except UnicodeEncodeError:
# print(response.content.decode("utf-8","ignore").replace('\xa9', ''))
response_text = response.content
finally:
pass # 处理断言
status = "PASS"
if _assert:
assert_results = []
for item in _assert:
try:
assert eval(item)
assert_results.append("PASS: <%s>" % item)
except AssertionError:
assert_results.append("FAIL: <%s>" % item)
status = "FAIL"
except Exception as e:
assert_results.append("ERROR: <%s>\n%s" % (item, repr(e)))
status = "ERROR" # 打印结果
print("="*80)
print("请求:")
print("Url: %s\nHeaders: %s\nData: %s" % (url, headers, data if isinstance(data, str) else json.dumps(data)))
print("-"*80)
print("响应:")
print(response_text)
if _assert:
print("-"*80)
print("断言:")
for assert_result in assert_results:
print(assert_result) def main():
if len(sys.argv) != 2:
print("缺少参数:json文件")
else:
postJson(sys.argv[1]) main()

**集成到Sublime **

  1. Sublime Text3 -> Tools -> Build System -> New Build System

    复制以下代码, 修改Python为你的Python3环境, 脚本路径为你的post_json.py路径, 保存为PostJson.sublimet-build
  • Windows 系统
{
"cmd": ["python3","C:/PostJson/post_json.py","$file"],
"file_regex": "^[ ] *File \"(...*?)\", line ([0-9]*)",
"selector": "source.json",
"encoding":"cp936",
}
  • Linux & Mac
{
"cmd": ["/Library/Frameworks/Python.framework/Versions/3.6/bin/python3","-u","/Users/apple/Applications/PostJson/post_json.py","$file"],
"file_regex": "^[ ] *File \"(...*?)\", line ([0-9]*)",
"selector": "source.json",
"env": {"PYTHONIOENCODING": "utf8"},
}

使用方法

建议安装PrettyJson插件

  1. 在Sublime text3中, 新建json文件,并保存为*.json
{
"url": "http://127.0.0.1:5000/api/user/login/",
"data": {"name": "张三","password": "123456"}
}
  1. 按Ctrl + B运行

项目路径

Github: PostJson

补充了以下功能:

  • 用例discover, 自动发现和批量执行
  • 生成报告
  • 命令行参数
    • verbose: 显示级别: 1. 只显示用例结果 2. 只显示响应文本(默认) 3. 显示请求,响应及断言信息
    • host: 指定服务器地址
    • env: 指定环境
    • timeout: 指定timeout
    • html: 指定输出html报告路径
    • log: 指定输出log路径
    • collect-only: 只列出所有用例

ToDo

  • 完善测试报告
  • 支持数据库对比
  • 支持执行Sql, Shell, Cmd命令等
  • 使用协程, 进行异步并发
  • 支持分布式执行
  • 支持定时执行
  • 进行持续集成

基于JSON的接口测试框架的更多相关文章

  1. 【转】基于Python的接口测试框架实例

    下面小编就为大家带来一篇基于Python的接口测试框架实例.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧   背景 最近公司在做消息推送,那么自然就会产生很多接口,测试 ...

  2. 基于python的接口测试框架设计(三)接口测试的框架

    基于python的接口测试框架设计(三)接口测试的框架 其实我这里用到的是unittest单元测试框架,,这个框架好就好在比较清楚,,setup terdown都可以处理一些初始化及完成后的工作 主要 ...

  3. 基于Python的接口测试框架实例

    文章来源:http://www.jb51.net/article/96481.htm 下面小编就为大家带来一篇基于Python的接口测试框架实例.小编觉得挺不错的,现在就分享给大家,也给大家做个参考. ...

  4. 基于LoadRunner构建接口测试框架

    基于LoadRunner构建接口测试框架 http://www.docin.com/p-775544153.html

  5. 基于python的接口测试框架设计(二)配置一些参数及文件

    基于python的接口测试框架设计(二)配置一些参数及文件 我这里需要基于我的项目配置的主要是登陆参数.以及baseURL ,把这些放在单独的文件里  毕竟导入的时候方便了一些 首先是url 图略 建 ...

  6. 基于python的接口测试框架设计(一)连接数据库

    基于python的接口测试框架设计(一)连接数据库 首先是连接数据库的操作,最好是单独写在一个模块里, 然后便于方便的调用,基于把connection连接放在__init__()方法里 然后分别定义D ...

  7. 基于Python的接口测试框架

    分析 接口是基于HTTP协议的,那么说白了,就是发起HTTP请求就行了,对于Python来说比较简单.直接使用requests就可以很轻松的完成任务. 架构 整个框架是比较小的,涉及的东西也比较少,只 ...

  8. [转]基于Python的接口测试框架

    http://blog.csdn.net/wyb199026/article/details/51485322 背景 最近公司在做消息推送,那么自然就会产生很多接口,测试的过程中需要调用接口,我就突然 ...

  9. 基于 python 的接口测试框架

    项目背景 公司内部的软件采用B/S架构,管理实验室数据,实现数据的存储和分析统计.大部分是数据的增删改查,由于还在开发阶段,所以UI界面的变化非常快,之前尝试过用python+selenium进行UI ...

随机推荐

  1. .netCore 简易Web 项目

    static async Task Main(string[] args) { var _httpListener = new HttpListener(); _httpListener.Prefix ...

  2. 拦截器中获取不到controller注解问题

    刚刚在测试接口的时候发现一个奇怪的问题:通过拦截器获取 controller 类注解,有些能获取到,有些又不能获取到,见鬼了. [环境]: 1. springboot :2.2.0.RELEASE [ ...

  3. PHP 的闭包

    匿名函数 提到闭包就不得不想起匿名函数,也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它.声明一个匿名函数是这样: 1 $func = function() { 2 3 }; //带结 ...

  4. 【转载】程序设计过程中SQL语句Where 1=1的作用

    在Asp.Net网站或者Java网站的程序设计的过程中,很多时候我们可以看到拼接SQL语句的写法的时候都可以看到最前面有个Where 1=1这个条件,其实Where 1=1这是个恒等式,SQL语句写成 ...

  5. var img = new Image()

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 流程控制 while for

    循环执行 计算机最擅长的功能之一就是按照规定的条件,重复执行某些操作,这是程序设计中最能发挥计算机特长的程序结构. 1.while语句 while(表达式){ 各种语句.... } 当表达式的值为tr ...

  7. NLP使用pytorch框架,pytorch安装

    pytorch的安装方法及出现问题的解决方案: 安装pytorch,使用pip 安装,在运行代码的时候会报错,但是导包的时候不会报错,因此要采用conda的方式安装   1.找到miniconda的网 ...

  8. iveiw DatePicker 只能选择本月之前的日期,本月包括之后都不能选择

    日期判断只能选择本月之前的日期 <DatePicker type="date" :options="options3" format="yyyy ...

  9. Windows——Thinkpad 开机显示pwmtr64v.dll找不到指定的模块

    解决方法:进入设备管理器,展开系统设备分页,找到Lenovo Power Manager ,右键,更新驱动程序,浏览计算机上的驱动程序, 让我从计算机上的可用驱动程序列表中选取,选择Lenovo Po ...

  10. Nginx服务优化及优化深入(配置网页缓存时间、日志切割、防盗链等等)

    原文:https://blog.51cto.com/11134648/2134389 默认的Nginx安装参数只能提供最基本的服务,还需要调整如网页缓存时间.连接超时.网页压缩等相应参数,才能发挥出服 ...