App接口测试工具之apimock

app接口mock server端返回一工具,一剑在手,跟我走! app崩溃就靠它了

优势

  1. 动态实时mock
  2. 命令配置灵活,键值支持精确及正则模糊检索,提供多个fuzz功能
  3. 容易理解,方便易用

适用场景

app对服务端返回的容错测试

服务端返回一旦出错后果很严重,app轻则ui异常重则崩溃,像api 404,502,长时间无返回,延迟, 返回空body,键值错,无值,异常值这几类一般必测

项目中使用该工具后效率有了明显提升


原理

  • 如何实时mock?

app通过pc上fiddler代理访问api

通过运行proxy xxx 给mock server 注入mock 配置,支持重置

借助fiddlerscript实现包转发给mock server,server根据运行时动态配置对包进行劫持修改,修改后再返还给fiddler

fiddler.js 重写OnBeforeResponse将指定包劫持转发给mockserver

static function OnBeforeResponse(oSession: Session) {
if (isautocap && oSession.HostnameIs(filterUrl) && oSession.responseCode == 200) {
oSession.utilDecodeResponse()
var rawbody = System.Text.Encoding.UTF8.GetString(oSession.responseBodyBytes);
var j=Fiddler.WebFormats.JSON.JsonDecode(rawbody)
if(typeof(j.JSONObject) == "object" && Object.prototype.toString.call(j.JSONObject).toLowerCase() == "[object hashtable]" && !j.JSONObject.length) {
try {
var api = oSession.PathAndQuery.split('?')[0]
rawbody = api + ':' + rawbody
var mockbody = mock('127.0.0.1', 8390, rawbody)
j=Fiddler.WebFormats.JSON.JsonDecode(mockbody)

mockserver.py 执行mock


def prep(self,data):
api, data = data.split(':', 1)
data = json.loads(data, encoding="utf8")
mock = {}
data['mock'] = mock
if api in self.api or not self.api:
try:
data = self.mock('', data)
  • 关键字索引及fuzz

索引找response中的关键字,并修改这个项的值

def key(data):
for k in self.key:
v= self.value[k]
if ':' in k:
str,k = k.split(':',1)
if str.lower() in ['regex','re','regexp']: data = regexpsearch(data,k,v) #关键字或正则模糊查找
else:
l_key= k.split('.')
data = exactsearch(data,l_key,v) #精确查找
return data

mockfun = {
'body': lambda: body(self.body),
'key': lambda: key(data),
'': lambda: data,
'clear':lambda : self.init()}
return mockfun[self.type]()

修改的值可以是具体值或者body,也可以是fuzz函数 也可自行实现其他fuzz

def setstrshorten(json, k,v):
v=str(v)
json[k] = (len(v) <= 3) and v or v[0:len(v) - random.randint(1, len(v)-1)]

def setstroverlen(json, k,v):
v=str(v)
n = 1025
# n=4294967294 max string ,..dot use!
for i in range(0, n): v += '1'
json[k] = v

def setstrillega(json, k,v):
json[k] = str(v) + ',*&#%()='[random.randint(1, 8) - 1] + 'H1 \u266a@\u5c0f\u8776\u6c42\u5b88\u62a4'

list = { 'del': lambda: delkey(json,k),
...
'none': lambda: set(json,k,None),
'0': lambda: set(json,k,0),
'-1': lambda: set(json,k,-1),
'maxlong': lambda: set(json, k, 9223372036854775808),
'*n': lambda: setintmultin(json, k,kv),
'cut': lambda: setstrshorten(json, k, kv),
'overlen': lambda: setstroverlen(json, k, kv),
'illega': lambda: setstrillega(json, k, kv),
...
}
return list[type]()
  • 控制台下发mock命令

python proxy.py -a /api/user/get -k errno=1 劫持api为/api/user/get,原response中errnor字段修改为1
python proxy.py -a /api/user/get -k re:name=”H1 \u266a@\u5c0f\u8776\u6c42\u5b88\u62a4″ 正则索引含name的修改为带乱码符号字符串
python proxy.py -r 1 清空mockserver中配置
python proxy.py -d 2g 模拟延迟2g网络
python proxy.py -b {} 返回空body
python proxy.py -b {xxx{” 返回非json格式body
python proxy.py -a /api/user/get -k re:name=fun:del 模糊查找name关键字,将其键删除
python proxy.py -a /api/user/get -k data.uid=fun:maxint path查找 data节点下uid关键字 ,修改为溢出的int

是不是很容易理解


未来

考虑后续与思寒的appcrawler做插件对接,做自动遍历的mock测试


开源地址

https://github.com/zhangzhao4444/Apimock

如有bug和好想法可及时联系我

,

* 注:本文来自网络投稿,不代表本站立场,如若侵犯版权,请及时知会删除