python mock接口测试_App 接口测试工具之 apimock (动态 mock 服务器返回)

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

优势

动态实时 mock

命令配置灵活,键值支持精确及正则模糊检索,提供多个 fuzz 功能

容易理解,方便易用

适用场景

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 测试

开源地址

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值