最近社区用 anyproxy 的挺多,我再来凑一波热闹
写这个工具,主要有几个原因:
关于健壮性测试,模糊测试的一些描述,我希望大家可以去思寒的帖子里看,我也是从他那里出发的,我想做的东西,和他帖子里讲到的差不多,不过我又加上了另外的一些规则,总的来说,第一阶段我总结了下需求,大致如下:
调研阶段,为了实现第一阶段的需求,并且结合公司的技术栈(python),主要是搜 github 和 google,排除了下面这些:
所以,最后选用的技术栈和工具是:
可以方便的模块化,打包成命令行工具,只有一个字,轻
因为这是一个依附于 anyproxy 的 mock 工具,所以 anyproxy 的 rule_file 这部分是一定要研究研究的,文档也很清楚了,我说说我踩过的坑:
shouldInterceptHttpsReq
replaceServerResDataAsync
,这个方法的 serverResData 参数,是一个 Buffer 对象已有功能:
usage: anymocker [-h] [-v] [-s SAVE] [-p PORT] [-m [MOCK [MOCK ...]]]
[-a [API [API ...]]] [-i [INJECT [INJECT ...]]]
[-d [DELETE [DELETE ...]]]
anymocker usage
Optional arguments:
-h, --help Show this help message and exit.
-v, --version Show program's version number and exit.
-s SAVE, --save SAVE file save path
-p PORT, --port PORT proxy port
-m [MOCK [MOCK ...]], --mock [MOCK [MOCK ...]]
mock value
-a [API [API ...]], --api [API [API ...]]
specify url
-i [INJECT [INJECT ...]], --inject [INJECT [INJECT ...]]
inject field
-d [DELETE [DELETE ...]], --delete [DELETE [DELETE ...]]
delete field
有了-i(增),-d(删),-m(改),可适应的需求范围就比较广了
看看效果
原图是:
全局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:
上述的几种方法可以适用于值的修改,但是有的时候需要根据原始值来进行 fuzzy 化处理再返回,也是可以做到的,需要把 jsonpath 的值指定为 FUZZ,fuzzy 化的规则主要有以下几个:
//全局mock,把text,title,name都模糊处理
$ anymocker -m $..title=FUZZ $..name=FUZZ
效果图:
可见第一个 “小脚太太和” 的 title 被随机减去了一些字符,name 返回了空;第二个 name“萌宠” 前后都加了随机字符,title 返回了空,第三个 “人文” 的 name 和 title 前都加了随机字符
由上述的实验看来,工具的完成情况还不错,对于 mock 和 fuzz 都能做到,我举得栗子比较浅,但实际上它可以构造出很复杂的规则,测试数据和该走线上的可以很好的分离,而且由于是轻量级命令行的(就是个 node 模块),跨平台也能使用,也可以很方便的集成到 CI。我自己对这种类型的测试还有一点别的思考: