在 anyproxy 上做 mock 和 fuzz 测试
引言
写这个工具,主要有几个原因:
最近老大在尝试不同视角的测试----健壮性测试,任务下来,所以挽起袖子就开撸了
app很可能因为后端api做了变更,返回了一个异常的值而出现难以预知的问题,健壮性受到碰撞,所以这种测试是有实际价值的
思寒的一篇帖子《基于 fuzz 技术验证移动端 app 的健壮性》我觉得挺好玩,这里要非常非常感谢他提供的思路,从下面的回复也可看出来大家还是比较感兴趣,而他因为遇到一些问题尚未开源,所以我挽起袖子就开撸了
社区里最近用anyproxy的挺多,我想说我们厂应该是最早开始用anyproxy的,流量测试中也使用到了这个工具。现在大家都开始定制,我表示不服,所以挽起袖子就开撸了
最近有幸被拉到了社区的技术专家群,趁着分红前多发一篇吧,哈哈
0x00
关于健壮性测试,模糊测试的一些描述,我希望大家可以去思寒的帖子里看,我也是从他那里出发的,我想做的东西,和他帖子里讲到的差不多,不过我又加上了另外的一些规则,总的来说,第一阶段我总结了下需求,大致如下:
只支持json结果的mock和fuzz
该走线上的还走线上,可针对某个具体api做修改
能够记录原始的request和response
在json结果中,能够指定某个key or value 进行增、删、改
fuzzy化,根据原值随机返回fuzz值
轻量级 ,方便用于CI,自动化测试,而并非动辄就写个系统
跨平台
0x01
调研阶段,为了实现第一阶段的需求,并且结合公司的技术栈(python),主要是搜github 和 google,排除了下面这些:
whistle ,太复杂
rap,GUI界面很贴心,但是主要是为了方便前端调试,生成模板,适合后端服务还没有起来的情况
mock-server,虽然python很贴合,文件保存这点做的好,但是不太方便做mock和fuzz
moco,东西很好,也有点重,java栈,之前社区有同学也做过moco + anyproxy的分享
所以,最后选用的技术栈和工具是:
nodejs
anyproxy
jsonpath
mockjs
可以方便的模块化,打包成命令行工具,只有一个字,轻
0x02
因为这是一个依附于anyproxy的mock工具,所以anyproxy的rule_file这部分是一定要研究研究的,文档也很清楚了,我说说我踩过的坑:
截取https的请求,并不是在anyproxy的启动options里把type设置为‘https’,而是把根据rule_file里的
shouldInterceptHttpsReq
做值的替换,肯定要用到
replaceServerResDataAsync
,这个方法的serverResData参数,是一个Buffer对象在用jsonpath 定位后,因为我的需求里面是有api 级别的mock和global级别的mock,也有两者都有的(api会覆盖global),这在怎么区分命令行参数,以及对类似 $..name 这样的值做mock或fuzz时,增加了一定难度
已有功能:
-s 参数是指定原始的request和response的保存路径
-p 指定anyproxy启动端口
-a 指定具体api,可以只针对这个api的返回数据做mock
-m 后面跟jsonpath表达式和值,比如$..name=fenfenzhong,即可把返回的结果里,所有name属性都改为fenfenzhong
-i 后面跟jsonpath表达式和值,可以在返回数据里置入你想要的值,对于一些由字段控制的UI特别有效
-d 后面跟jsonpath表达式,比如$..title,可以把返回结果里的所有title属性都删除
有了-i(增),-d(删),-m(改),可适应的需求范围就比较广了
0x03
看看效果
原图是:
全局mock,把所有name都换成fenfenzhong,所有text都换成66666,所有title都换成lgtm
$ anymocker -s save -m $..name=fenfenzhong $..text=66666 $..title=lgtm
解析之后,mock规则长这样:
{
"global": {
"mock": [
"$..name=fenfenzhong", "$..text=66666", "$..title=lgtm"
]
}, "api": {}}
效果图是:
//全局mock,把所有text都换成66666,所有title都换成lgtm,删除所有的name属性,并且植入一个属性 qa=douban
// 本来想删除所有的title 属性的,结果。。崩溃啦
$ anymocker -s save -m $..text=66666 $..title=lgtm -i $.qa=douban -d $..name
解析之后,mock规则长这样:
{
"global": {
"mock": [
"$..text=66666", "$..title=lgtm"
], "inject": [
"$.qa=douban"
], "delete": [
"$..name"
]
}, "api": {}}
效果图是:
摘取某一个返回的json:
当既指定了api,又有全局规则的时候,会先应用全局的规则,然后再应用api的规则,当两者涉及到的属性名一样时,api的会覆盖全局的。如果指定了api但是却没有命中,则只应用全局的,或者直接返回原始值
//全局mock,把所有text都换成66666,所有title都换成lgtm,所有name都换成fenfenzhong,再针对具体的/api/v2/note ,把text换成sixsixsix,再增加一个属性qa=douban
$ anymocker -a /api/v2/note/ -i $..qa=douban -d -m $..text=sixsixsix -m $..name=fenfenzhong $..text=66666 $..title=lgtm
解析之后,mock规则长这样:
{
"global": {
"mock": [
"$..name=fenfenzhong", "$..text=66666", "$..title=lgtm"
]
}, "api": {
"/api/v2/note/": {
"mock": [
"$..text=sixsixsix"
], "inject": [
"$..qa=douban"
], "delete": []
}
}}
全局mock的效果图,和之前一样
但是一个具体的日记条目里,可以看到返回的值里已经多了一个qa=douban,mock后的text值全变为了sixsixsix:
0x03
上述的几种方法可以适用于值的修改,但是有的时候需要根据原始值来进行fuzzy化处理再返回,也是可以做到的,需要把jsonpath的值指定为FUZZ,fuzzy化的规则主要有以下几个:
number,string,和boolean类型的才能被fuzzy化
每种类型都有一定几率返回null
数字会随机放大缩小倍数,string会随机变为空串‘’
//全局mock,把text,title,name都模糊处理
$ anymocker -m $..title=FUZZ $..name=FUZZ
效果图:
可见第一个“小脚太太和” 的title被随机减去了一些字符,name返回了空;第二个name“萌宠”前后都加了随机字符,title返回了空,第三个“人文” 的name 和title 前都加了随机字符
最后
由上述的实验看来,工具的完成情况还不错,对于mock和fuzz都能做到,我举得栗子比较浅,但实际上它可以构造出很复杂的规则,测试数据和该走线上的可以很好的分离,而且由于是轻量级命令行的(就是个node模块),跨平台也能使用,也可以很方便的集成到CI。我自己对这种类型的测试还有一点别的思考:
这种类型的测试,主要是用随机的值,或者人为构造的极限值去挑战app,在一定程度上,能够检测app的健壮性
外部服务的失效往往会对重依赖的app产生比较大影响,拿到null值的可能性增加
这类问题的优先级可能不是那么高,怎样去构造一个现实可能出现的异常数据(如果真实不可能出现,那即使崩溃了其实也说明不了什么),对测试人员能力有较高要求
长按二维码识别关注,您的支持是我们最大的动力。
公众号:测试梦工厂
QQ一群:300897805
在 anyproxy 上做 mock 和 fuzz 测试的更多相关文章
- 使用peach工具进行fuzz测试
本文简要介绍了Fuzz 工具Peach的使用,并通过文件格式 Fuzz举例阐述了 Peach Pit 文件的编写. 本文转自“绿盟科技博客”:http://blog.nsfocus.net/peach ...
- 用上这个 Mock 神器,让你的开发爽上天!
前端的痛苦 作为前端,最痛苦的是什么时候? 每个迭代,需求文档跟设计稿都出来了,静态页面唰唰两天就做完了.可是做前端又不是简单地把后端吐出来的数据放到页 面上就完了,还有各种前端处理逻辑啊. 后端 ...
- Centos6.2上做nginx和tomcat的集成及负载均衡(已实践)
Centos6.2上做nginx和tomcat的集成及负载均衡 ---------------------------------------------------------Jdk-------- ...
- Web测试要点 做移动端的测试,也做web端的测试,甚至后面桌面端的测试和后台的测试也做了,基本上把我们产品各个端都玩了一轮
Web测试要点 一.功能测试 1.链接测试 (1).测试所有链接是否按指示的那样确实链接到了该链接的页面: (2).测试所链接的页面是否存在: (3).保证Web应用系统上没有孤立的页面(所谓孤立 ...
- 阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!
最近栈长注意到阿里开源了自家的 Mock 工具:TestableMock,该工具号称最轻量.简单.舒适的 Mock 测试工具,功能十分强大,媲美 PowerMock,用法比 Mockito 还要简洁, ...
- 做web开发和测试,修改hosts指定某个域名访问某个特定的IP后,如何使hosts立即生效的方法
本文转自SUN'S BLOG,原文地址:http://whosmall.com/post/143 hosts的配置方法: 在windows系统中,找到C:\windows\system32\drive ...
- Swift - 使用MapKit显示地图,并在地图上做标记
通过使用MapKit可以将地图嵌入到视图中,MapKit框架除了可以显示地图,还支持在地图上做标记. 1,通过mapType属性,可以设置地图的显示类型 MKMapType.Standard :标准地 ...
- 如何在WebGL全景图上做标记
WebGL可以用来做3D效果的全景图呈现,例如故宫的全景图.但有时候我们不仅仅只是呈现全景图,还需要增加互动.故宫里边可以又分了很多区域,例如外朝中路.外朝西路.外朝东路等等.我们需要在3D图上做一些 ...
- Android 如何将手机屏幕投影到 PC 屏幕上或者投影仪上做演示?
Android 如何将手机屏幕投影到 PC 屏幕上或者投影仪上做演示? 公司开发款APP,要给领导演示,总不能用手机面对面演示吧.所以找了好久,找到一款体验超好的: Total Control-帮助你 ...
随机推荐
- python进阶笔记 thread 和 threading模块学习
Python通过两个标准库thread和threading提供对线程的支持.thread提供了低级别的.原始的线程以及一个简单的锁.threading基于Java的线程模型设计.锁(Lock)和条件变 ...
- 数据导出到excel
jsp页面: 数据table: <form action="/export.jsp" method="post" id="expform&quo ...
- C语言格式化输入不定长数组
先随便写写,有空再整理. 直接贴代码 #include <stdio.h> #include <stdlib.h> //从一行标准输入中格式化输入一个不定长数组 void in ...
- 内存管理 - MEMORY POOL
内存池优势: 效率高,频繁的new和delete效率低下 减少内存碎片,反复向系统申请和释放内存会产生大量内存碎片 防止内存泄露 内存池设计思路: 内存池可以根据实际需要,设计成不同的样子.下面是针对 ...
- 配置apache apache服务器如何配置多站点
http://jingyan.baidu.com/article/5225f26b07605be6fa090890.html 让Apache在启动时能加载虚拟主机模块. 打开Apache安装目录下co ...
- DotNetBar 第2课,窗口设置 Ribbon Form 样式
1. 新增 windows 窗体时,选 Ribbon Form 2. 窗体继承 Office2007RibbonForm 3. 设计窗口下面,删除 删除styleManager1 组件 窗口效果如下 ...
- 创建 Transact-SQL 作业步骤
创建 Transact-SQL 作业步骤 在对象资源管理器中,连接到 SQL Server 数据库引擎实例,再展开该实例. 展开"SQL Server 代理",创建一个新作业或右键 ...
- C# 加载 SQLite DLL问题
/********************************************************************************* * C# 加载 SQLite DL ...
- OpenGL 4.5 Core Profile管线(GLSL与应用程序接口详解)【未完成】
之前写过一篇博客,OpenGL管线(用经典管线代说着色器内部),说的主要是OpenGL的经典管线.大家都知道,现代OpenGL已经弃用(从OpenGL 3.0开始)经典管线功能(glBegin,变换矩 ...
- 【转】构建C1000K的服务器(1) – 基础
原文来自 ideawu 构建C1000K的服务器(1) – 基础 著名的 C10K 问题提出的时候, 正是 2001 年, 到如今 12 年后的 2013 年, C10K 已经不是问题了, 任何一个普 ...